Repository navigation
Minify state var names and allow installing a name resolver after states exist - #7337
Open
benedikt-bartscher wants to merge 189 commits into
Open
benedikt-bartscher wants to merge 189 commits into
benedikt-bartscher wants to merge 189 commits into
Conversation
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
When a parent and child state have the same minified name, substate resolution can fail because the leading segment is stripped incorrectly. This change adds a flag to skip stripping only on the initial recursive call, ensuring correct resolution even in name collision scenarios.
…into late-bound-wire-names
…into late-bound-wire-names
…into late-bound-wire-names # Conflicts: # reflex/minify.py
…into late-bound-wire-names
…ler spawning and minify test configs
…into late-bound-wire-names # Conflicts: # reflex/minify.py # reflex/reflex.py # reflex/state.py # tests/units/minify_helpers.py # tests/units/reflex_base/test_registry.py # tests/units/test_minify.py
…ource and define the state-read pattern once
…into late-bound-wire-names
…into late-bound-wire-names
…inification - state.js: keep the main_state_name prefix check in isStateful, with main's non-string event name guard and nested event normalization. - vars/base.py, tests: keep both sides' imports and new tests. - docs/api-reference/cli.md: keep compile and minify, drop the deleted component command. - test_context_js_template.py: context_template no longer takes state_name.
…into late-bound-wire-names - tests/benchmarks/test_shared_state.py: _always_dirty_substates holds state classes, so the shared-state harness adds SharedStateBaseInternal itself.
Ported upstream changes into the resolver-aware code: - Context template: hydrate_and_load (reflex-dev#7064) gets a resolved wire name in InternalNames (replacing hydrate), alongside upstream's state schema and initial state hashes. state.js reads app.hydrate_and_load and app.update_vars_internal instead of hardcoded default names, and the handshake query (token + scheme) is built for the warm-up socket too. - State reads use upstream's useStateContext (reflex-dev#7441), keyed by the state's resolved full name, into the branch's prefixed local. - Upstream made unknown substates non-fatal (reflex-dev#7435) and dropped backend_state_mismatch; the fatal minification scheme mismatch keeps its own flag (backend_scheme_mismatch) gating events, updates and reconnects. - The frontend state schema hash (reflex-dev#7553) hashes resolver-independent names; the scheme digest already covers the wire names. - The processor's hydrate/hydrate_and_load/on_load_internal lookups cache handlers, not names, so they follow a resolver installed later. - BaseStateToken._state_key and client storage application (_apply_client_storage_vars) use default names and wire var keys. - get_substate keeps upstream's loop but only lets the first segment name the state itself; get_name/get_full_name stay function-wide caches so a resolver install clears every class, and also clears _get_substate_path. - on_connect sets up per-SID state before upstream's new first await. - pyStrAt avoids Array.prototype.at, which the state.js tests forbid.
…inification Ported upstream changes into the resolver-aware code: - Context template: hydrate_and_load (reflex-dev#7064) gets a resolved wire name in InternalEventNames (replacing hydrate), alongside upstream's state schema and initial state hashes. state.js reads app.hydrate_and_load and app.update_vars_internal instead of hardcoded default names, and the handshake query (token + scheme) is built for the warm-up socket too. - State reads use upstream's useStateContext (reflex-dev#7441), keyed by the state's resolved full name, into the prefixed local. - Upstream made unknown substates non-fatal (reflex-dev#7435) and dropped backend_state_mismatch; the fatal minification scheme mismatch keeps its own flag (backend_scheme_mismatch) gating events, updates and reconnects. - The frontend state schema hash (reflex-dev#7553) hashes resolver-independent names; the scheme digest already covers the wire names. - The processor's hydrate/hydrate_and_load/on_load_internal lookups cache handlers, not names, so they follow a resolver installed later. - BaseStateToken._state_key keys by the resolver-independent name. - get_substate keeps upstream's loop but only lets the first segment name the state itself; get_name/get_full_name stay function-wide caches so a resolver install clears every class, and also clears _get_substate_path. - on_connect sets up per-SID state before upstream's new first await. - pyStrAt avoids Array.prototype.at, which the state.js tests forbid.
…into late-bound-wire-names Brings in reflex-dev#6100's merge of upstream/main. Its conflicts here are the reflex-dev#6100 spellings of code this branch already resolved (InternalEventNames vs InternalNames, the hook's state name, tests of state/event-only minification), so this branch's versions are kept and the tree is unchanged.
A handler with no minify.json entry keeps its Python name, which can be the id another handler of its state was given, e.g. when it is added before 'reflex minify sync' runs. Registering it overwrote the other, so an event for one ran the other. Registration now raises when two handlers of a state resolve to the same name. refresh_keys rebuilt the substate sets from base_states, which still holds a state a module reload removed, so installing a resolver after such a reload put the removed state back into the tree. It now re-keys the substate sets as they are.
…into late-bound-wire-names
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #6100 — the diff includes its commits until that merges. The changes specific to this PR are in fb6992b and the merges of
explicit-event-id-minificationthat follow it.What this adds
Var name minification.
REFLEX_MINIFY_VARS=1shortens state var keys on the wire using a new optionalvarssection inminify.json(still schema version 1; older files load with no vars). A minified key is just its id, so a delta goes from{"a.b": {"items_rx_state_": []}}to{"a.b": {"c": []}}.reflex minify init/sync/validate/list/lookupcover vars, and the scheme digest includes them. Var ids that every JS object already has (constructor,__proto__, …) or that end in_rx_state_are rejected.A name resolver can be installed after states exist.
RegistrationContext.set_name_resolverrebuilds the Vars every registered state holds. Backend dependency tracking andVarData.field_dependenciesnow key on classes and the resolver-independent default name, so they never go stale. This lets in-processAppHarnesstests run fully minified. A Var built from state Vars before the install (e.g. a module-level component imported beforeminify.jsonwas loaded) is not fixed; compiling fails with a message naming each stale reference instead of shipping a broken frontend.One place builds wire keys.
format_var_key/format_state_var(which reads through the prefixed localformat_state_localfrom #6100) replace the ad-hocname + FIELD_MARKERconcatenations;update_vars_internalmaps keys back through a per-state lookup, andstate.jsreads the hydrated flag's key from the compiled context instead of hardcoding it.Notes
setvarstill sends the Python var name: it dispatches through the class hierarchy, where a per-state id would be ambiguous.REFLEX_PERF_MODE's check for stringified vars keys on the field marker, so it doesn't see minified vars.is_hydratedare minified too; nothing in the frontend reads them by name anymore.NameResolver.resolve_var_name,reflex_base.utils.format.format_var_key/format_state_var.Testing
update_vars_internalwith minified keys, and the CLI.tests/integration/test_minification.pynow runs in-process with framework states and vars minified.ComponentState, cookie/localStorage persistence across tabs, dynamic routes; websocket frames carry no var or state names.🤖 Generated with Claude Code