Add view share support#165
Conversation
Extract shared view data into the component scope so that variables
registered via View::share() are accessible without manually calling
$__env->shared('key').
Shared data is extracted after component data (EXTR_SKIP) so that
props and slots always take priority over shared variables, matching
Blade's array_merge($shared, $data) behavior.
|
/benchmark attributes |
|
/benchmark no-attributes |
|
/benchmark class |
|
/benchmark forwarding |
|
/benchmark aware |
|
/benchmark slot, |
Benchmark Result: Attributes
Median of 10 attempts, 5000 iterations x 10 rounds, 23.39s total To run a specific benchmark, comment |
Benchmark Result: No Attributes
Median of 10 attempts, 5000 iterations x 10 rounds, 18.98s total To run a specific benchmark, comment |
Benchmark Result: Class
Median of 10 attempts, 5000 iterations x 10 rounds, 32.47s total To run a specific benchmark, comment |
Benchmark Result: Default
Median of 10 attempts (* = outlier, excluded from result), 5000 iterations x 10 rounds, 45.67s total To run a specific benchmark, comment |
Benchmark Result: Forwarding
Median of 10 attempts (* = outlier, excluded from result), 5000 iterations x 10 rounds, 93.14s total To run a specific benchmark, comment |
Benchmark Result: Aware
Median of 10 attempts, 5000 iterations x 10 rounds, 100.99s total To run a specific benchmark, comment |
calebporzio
left a comment
There was a problem hiding this comment.
Love how small this is for the limitation it removes — one line in the wrapper and the priority order falls out of EXTR_SKIP for free.
What I verified locally (with this branch merged into current main):
- Full suite passes (208 passed).
- A prop wins over a shared variable of the same name, matching Blade's
array_merge($shared, $data)semantics. - Shared values re-read on every render — mutating a shared var between renders shows the new value.
- Sharing a variable named
slotdoesn't leak into components (compared identical to Blade). - Perf cost is real but modest:
no-attributeswent 1.26ms → 1.36ms blaze time for me (~+8%, matching the CI +7.6%). Every component render now pays for thegetShared()extract whether or not it uses shared vars — I think that's an acceptable trade for matching Blade, but flagging it since it's our hottest path.
One real issue I found before this can merge — folded components silently freeze shared values at compile time:
// component: @blaze(fold: true) ... {{ $sharedValue }}
View::share('sharedValue', 'first-value');
Blade::render('<x-foldable.shared-fold />'); // "first-value" — folds, bakes the value
View::share('sharedValue', 'second-value');
Blade::render('<x-foldable.shared-fold />'); // still "first-value"; Blade would say "second-value"Today this failure is loud: the fold-time render throws an undefined variable, the Folder catches it and falls back to runtime. With this PR the fold-time render succeeds and bakes whatever happens to be shared during compilation — which for the typical View::share() use case (per-request data from middleware) means silently stale output.
One idea: only emit the extract($__env->getShared(), EXTR_SKIP) line in the non-folding wrapper variant (the wrapper already branches on $this->manager->isFolding() for the content handler), so fold attempts on shared-var components keep failing loudly and fall back to the runtime function, where the extract works. But you two know the folding/passthrough mechanics better than I do, so take that with a grain of salt — a documented "shared vars mark a component unsafe to fold" would also do it.
Verdict: needs that folding story resolved, then I'm happy with this. Thanks Sander!
Removes the "Auto-injecting
View::share()variables is not supported" limitation.After all the recent performance improvements, I figured we could add this support with minor impact.
Before
Shared variables required manual access:
After
Shared variables are available directly, matching Blade:
How it works
One line added to the generated function body:
This runs after slots and component data have already been extracted, so the priority order is: slots > props > shared, matching Blade's
array_merge($shared, $data)semantics. A prop passed to a component always wins over a shared variable with the same name.