From 8a7164b4b60ecb5224511d2117637d57b2a1391f Mon Sep 17 00:00:00 2001 From: Josh Hanley Date: Mon, 18 May 2026 13:09:46 +1000 Subject: [PATCH 1/2] Always abort fold when `@aware` prop is dynamic, regardless of safe list When an `@aware` prop is supplied dynamically by the parent, the fold must be aborted so the runtime `@aware` lookup survives. v1.0.12 added this guard, but routed the prop through the same `$unsafe` lookup that `safe:` subtracts from, so any prop listed in both was silently re-permitted and the fold proceeded. Short-circuit the aware-from-parent-dynamic case before it touches `safe:`/`$unsafe`. A `safe:` declaration is a promise about dynamic values passed on the component itself; it cannot apply to values that enter via `@aware`, because folding eliminates the `@aware` lookup entirely. Fixes livewire/flux#2613 --- src/Folder/Folder.php | 2 +- tests/Folder/FolderTest.php | 39 +++++++++++++++++++ .../foldable/input-aware-safe.blade.php | 9 +++++ 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 tests/fixtures/views/components/foldable/input-aware-safe.blade.php diff --git a/src/Folder/Folder.php b/src/Folder/Folder.php index eda0cdd..86b9689 100644 --- a/src/Folder/Folder.php +++ b/src/Folder/Folder.php @@ -104,7 +104,7 @@ protected function isSafeToFold(ComponentSource $source, ComponentNode $node): b && isset($node->parentsAttributes[$prop]) && ! $node->parentsAttributes[$prop]->isStaticValue() ) { - $dynamicAttributes[$prop] = $node->parentsAttributes[$prop]; + return false; } } diff --git a/tests/Folder/FolderTest.php b/tests/Folder/FolderTest.php index 4bb96d5..39c7c43 100644 --- a/tests/Folder/FolderTest.php +++ b/tests/Folder/FolderTest.php @@ -238,6 +238,45 @@ expect($folded)->toBeInstanceOf(TextNode::class); }); +test('does not fold components with dynamic aware prop from parent even when listed in safe', function () { + $input = ''; + + $node = app(Parser::class)->parse($input)[0]; + $node->setParentsAttributes( + app(AttributeParser::class)->parse(':type="$type"') + ); + + $folded = app(Folder::class)->fold($node); + + expect($folded)->toBeInstanceOf(ComponentNode::class); +}); + +test('folds components with aware prop listed in safe overridden by direct attribute', function () { + $input = ''; + + $node = app(Parser::class)->parse($input)[0]; + $node->setParentsAttributes( + app(AttributeParser::class)->parse(':type="$type"') + ); + + $folded = app(Folder::class)->fold($node); + + expect($folded)->toBeInstanceOf(TextNode::class); +}); + +test('folds components with static aware prop listed in safe from parent', function () { + $input = ''; + + $node = app(Parser::class)->parse($input)[0]; + $node->setParentsAttributes( + app(AttributeParser::class)->parse(':type="true"') + ); + + $folded = app(Folder::class)->fold($node); + + expect($folded)->toBeInstanceOf(TextNode::class); +}); + test('does not fold components with no blaze directive', function () { $input = ''; diff --git a/tests/fixtures/views/components/foldable/input-aware-safe.blade.php b/tests/fixtures/views/components/foldable/input-aware-safe.blade.php new file mode 100644 index 0000000..40d6010 --- /dev/null +++ b/tests/fixtures/views/components/foldable/input-aware-safe.blade.php @@ -0,0 +1,9 @@ +@blaze(fold: true, safe: ['type']) + +@aware(['type' => 'text']) + +@if ($type == 'number') + +@else + +@endif From 40c717c3822d13e4e9bc8249ed9877f6e6827989 Mon Sep 17 00:00:00 2001 From: Josh Hanley Date: Mon, 18 May 2026 13:31:26 +1000 Subject: [PATCH 2/2] Tighten test names and drop redundant override case --- tests/Folder/FolderTest.php | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/tests/Folder/FolderTest.php b/tests/Folder/FolderTest.php index 39c7c43..af00144 100644 --- a/tests/Folder/FolderTest.php +++ b/tests/Folder/FolderTest.php @@ -238,7 +238,7 @@ expect($folded)->toBeInstanceOf(TextNode::class); }); -test('does not fold components with dynamic aware prop from parent even when listed in safe', function () { +test('does not fold components if a dynamic prop comes from parent using aware even when marked as safe', function () { $input = ''; $node = app(Parser::class)->parse($input)[0]; @@ -251,26 +251,10 @@ expect($folded)->toBeInstanceOf(ComponentNode::class); }); -test('folds components with aware prop listed in safe overridden by direct attribute', function () { +test('folds components when a prop is passed directly even if aware is declared', function () { $input = ''; $node = app(Parser::class)->parse($input)[0]; - $node->setParentsAttributes( - app(AttributeParser::class)->parse(':type="$type"') - ); - - $folded = app(Folder::class)->fold($node); - - expect($folded)->toBeInstanceOf(TextNode::class); -}); - -test('folds components with static aware prop listed in safe from parent', function () { - $input = ''; - - $node = app(Parser::class)->parse($input)[0]; - $node->setParentsAttributes( - app(AttributeParser::class)->parse(':type="true"') - ); $folded = app(Folder::class)->fold($node);