Fix serialization of multiple closures on the same line#120
Merged
taylorotwell merged 4 commits intolaravel:2.xfrom Jan 8, 2026
Merged
Fix serialization of multiple closures on the same line#120taylorotwell merged 4 commits intolaravel:2.xfrom
taylorotwell merged 4 commits intolaravel:2.xfrom
Conversation
|
Hi @michaelruelas, These work nicely: $a = "a";
$b = "b";
$correct = Concurrency::driver('process')->run([fn () => $a, fn() => $b]);
$correct = Concurrency::driver('process')->run([fn () => "a", static fn() => "b"]);
// ["a", "b"]But these are still not working: $incorrect = Concurrency::driver('process')->run([fn () => "a", fn() => "b"]);
$incorrect = Concurrency::driver('process')->run([function () { return "a"; }, function () { return "b"; }]);
$incorrect = Concurrency::driver('process')->run([fn () => "a", function () { return "b"; }]);
// ["a", "a"]Is this a limitation of this PR? By the way, if I make one normal |
d8y
added a commit
to d8y/serializable-closure
that referenced
this pull request
Apr 4, 2026
When a closure (e.g. `static function()`) is returned from an arrow
function on the same line (`fn() => static function() { ... }`), the
token parser incorrectly captures the outer arrow function instead of
the inner closure. After deserialization the closure becomes a silent
no-op — returning a Closure object instead of executing the intended
logic, with no errors or failed jobs.
This happens because the inner closure is absorbed into the arrow
function's body during parsing and never collected as a separate
candidate. The existing candidate selection (PR laravel#120) only handles
sibling closures on the same line, not nested closures.
The fix adds an `extractNestedClosure()` method that, for short closure
candidates, extracts the inner function/closure from after the `=>`
operator and verifies it against the reflected closure's signature.
d8y
added a commit
to d8y/serializable-closure
that referenced
this pull request
Apr 4, 2026
When a closure (e.g. `static function()`) is returned from an arrow
function on the same line (`fn() => static function() { ... }`), the
token parser incorrectly captures the outer arrow function instead of
the inner closure. After deserialization the closure becomes a silent
no-op — returning a Closure object instead of executing the intended
logic, with no errors or failed jobs.
This happens because the inner closure is absorbed into the arrow
function's body during parsing and never collected as a separate
candidate. The existing candidate selection (PR laravel#120) only handles
sibling closures on the same line, not nested closures.
The fix adds an `extractNestedClosure()` method that, for short closure
candidates, extracts the inner function/closure from after the `=>`
operator and verifies it against the reflected closure's signature.
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.
Closes #119
Description
This pull request addresses an issue where
SerializableClosurewould incorrectly serialize the first closure found on a line when multiple closures were defined on that same line (e.g., arrow functions in an array or passed as arguments).Previously, the
ReflectionClosure::getCode()logic would greedily return the firstfnorfunctiondefinition it encountered on the source line. This PR introduces a robust candidate selection mechanism:ReflectionFunctionproperties (parent class ofReflectionClosure) such as:static fnvsfn).Benefit to End Users
This fix allows users to more reliably use arrow functions with Laravel's concurrency and background processing features (like
Concurrency::run()), where short closures are often defined inline on a single line. It removes a subtle data corruption bug where the wrong closure logic would be executed after deserialization.Why it doesn't break existing features
The implementation purely adds disambiguation logic to the code extraction phase. It follows existing parser patterns and adds a secondary validation step using official Reflection metadata. Existing unit tests (331 total) all pass, and the new disambiguation logic only triggers when the reflection data confirms a match.
Tests
New tests have been added in
tests/MultipleClosuresOnSameLineTest.phpcovering scenarios with different arguments, different static variables, and static/non-static mixtures.