Skip to content

Fix conditional slots being always rendered#134

Draft
ganyicz wants to merge 3 commits into
mainfrom
filip/compiled-slots
Draft

Fix conditional slots being always rendered#134
ganyicz wants to merge 3 commits into
mainfrom
filip/compiled-slots

Conversation

@ganyicz

@ganyicz ganyicz commented Mar 13, 2026

Copy link
Copy Markdown
Collaborator

Draft — this doesn't handle folded components yet. Slots inside conditionals will still always render when the component is folded. To fix this, we need to statically analyze the component and abort the fold when a slot is conditionally rendered.

The scenario

Wrapping <x-slot> in @if always renders the slot, even when the condition is false.

<x-card>
    @if(false)
    <x-slot name="header">
        Header
    </x-slot>
    @endif
</x-card>

The problem

Blaze extracted slot declarations at compile time, stripping them from their surrounding Blade directives. Runtime conditionals like @if were never evaluated around the slot.

The solution

We now compile slots inline alongside the rest of the template instead of extracting them upfront.

Fixes #119

@ganyicz ganyicz marked this pull request as draft March 13, 2026 13:25
calebporzio and others added 2 commits July 4, 2026 07:56
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Folding extracts slots at compile time, so a slot wrapped in a runtime
control structure (@if, @foreach, etc.) would always render regardless
of the condition. Detect unclosed control structures around call-site
slots and fall back to the regular compiler, which now evaluates them
at runtime.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@calebporzio

Copy link
Copy Markdown
Contributor

Took this for a spin today — nice work. I verified it against a repro of #119: on main, a slot wrapped in @if(false) always renders; on this branch the condition correctly evaluates at runtime for non-folded components.

I pushed two commits:

  • Merged main in (conflicts were test-only).
  • Handled the folded case from your draft note: the folder now detects a call-site slot sitting inside an unclosed control structure (@if, @unless, @foreach, etc.) and skips the fold, letting the regular compiler take over — which, with your changes, evaluates the conditional at runtime. That flips your foldable conditional slots test to passing.

Full suite is green locally (211 passed, 6 skipped). I also added truthy-condition comparison tests to make sure slots that should render still do, in both the folded and non-folded paths.

One thing I checked that this doesn't cover: #182 (slots declared inside an @include). That's a separate root cause — left notes on the issue.

Feel free to un-draft if you're happy with the fold-detection approach.

@github-actions

This comment was marked as off-topic.

@ganyicz

ganyicz commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator Author

I would prefer a more robust solution for parsing of directives instead of just adding a bunch of regexes.

We already hack around directive parsing using a separate instance of blade compiler, which ensures we stay aligned with Laravel. It would be ideal to come up with something that would cover all these needs.

Additionally, this solution would only work with the listed directives:

$pattern = '/\B@(end)?(if|unless|isset|switch|foreach|forelse|for|while|empty)\b(\s*\()?/'

Wrapping a slot in @auth, @guest, @env or any custom blade condition would cause the same issue.

I envision something that detects if a slot is wrapped in any directive (to be safe).

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

<x-slot> inside @if is always rendered when Blaze is enabled

2 participants