Skip to content

Compile-time fold executes Livewire's wire:key runtime statement, poisoning SupportCompiledWireKeys for subsequent mounts #204

Description

@brightfieldworks-ai

Blaze folds a component by rendering it at compile time, with dynamic attributes replaced by BLAZE_PLACEHOLDER_N_. When the folded component carries a wire:key, Livewire's precompiler has injected a runtime statement immediately before it:

SupportCompiledWireKeys::$currentLoop['key'] = <expr>;

Folding executes that statement, writing the placeholder into a public static.

Because compilation happens inside a request's render, the next <livewire:...> to mount inherits the poisoned value and receives a key like:

lw-2542294403-0-BLAZE_PLACEHOLDER_0_-1     # cold compile
lw-2542294403-0-1                          # warm process

This is not cosmetic

On the next Livewire update the key no longer matches, SupportNestingComponents::hasPreviouslyRenderedChild() returns false, and the child component is fully re-mounted with a new id rather than being stubbed and reused.

Verified with a positive control through the real Livewire update endpoint:

  • cold arm — key mismatch, child re-mounted with a new id, old id absent from the response
  • warm arm — key matches, child stubbed and reused

Reproduction

  1. php artisan view:clear
  2. Issue a request that renders a page containing a folded component with a wire:key, followed by a nested <livewire:...> mount
  3. Compare the nested component's wire:key against the same request in a warm process

Nothing is baked into any compiled file — it is process-global runtime state mutated during compilation.

Versions

  • livewire/blaze v1.0.15
  • livewire/livewire v4.4.0
  • livewire/flux v2.16.0
  • PHP 8.4+

The trigger in our case is Flux's select/option/variants/default.blade.php:10, which carries wire:key="{{ $value }}" — but nothing here is specific to Flux. Any folded component carrying a wire:key should reproduce it.

Scope

Only cold compiles are affected, so artisan optimize hides it entirely in production. Local development and CI reach it.

We have not attempted a fix on our side: the only lever available to us is disabling the fold for that component, which costs several hundred extra Blade component instantiations per render to remove a symptom that never reaches production. A ComponentFolded listener does not work either — there is no pre-fold hook, so it can only reset rather than save/restore, and it would collide keys inside loops.

Which package is the right place to change this is your call — the interaction spans the precompiler's runtime statement and the fold that executes it.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions