Skip to content

Commit 80c1574

Browse files
committed
feature twigphp#4216 Swap BC layer for yield-ready and reclaim perf loss (nicolas-grekas)
This PR was merged into the 3.x branch. Discussion ---------- Swap BC layer for yield-ready and reclaim perf loss Follows twigphp#3999 Fix twigphp#4146 Fix twigphp#4103 When `use_yield` is set to false (the default), this PR reverts the implementation of the `render()` method to use a wrapping output buffer instead of hooking between each steps of generators. In this mode, the behavior of the yield method is not "pure": it triggers a mix of yield and echo. But this is fine for render and display methods. When `use_yield` is set to `true`, we skip that wrapping output buffer. This makes twig compatible with fibers (and this also makes compilation fail if a non-YieldReady extension is found.) That makes the name of the option not ideal, but BC rulez FTW. Commits ------- 5d1a19a Swap BC layer for yield-ready and reclaim perf loss
2 parents 17997cf + 5d1a19a commit 80c1574

File tree

2 files changed

+60
-58
lines changed

2 files changed

+60
-58
lines changed

src/Node/FlushNode.php

+7-4
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,12 @@ public function __construct(int $lineno, string $tag)
2929

3030
public function compile(Compiler $compiler): void
3131
{
32-
$compiler
33-
->addDebugInfo($this)
34-
->write("flush();\n")
35-
;
32+
$compiler->addDebugInfo($this);
33+
34+
if ($compiler->getEnvironment()->useYield()) {
35+
$compiler->write("yield '';\n");
36+
}
37+
38+
$compiler->write("flush();\n");
3639
}
3740
}

src/Template.php

+53-54
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,17 @@ public function displayBlock($name, array $context, array $blocks = [], $useBloc
166166
*/
167167
public function renderParentBlock($name, array $context, array $blocks = [])
168168
{
169+
if (!$this->useYield) {
170+
if ($this->env->isDebug()) {
171+
ob_start();
172+
} else {
173+
ob_start(function () { return ''; });
174+
}
175+
$this->displayParentBlock($name, $context, $blocks);
176+
177+
return ob_get_clean();
178+
}
179+
169180
$content = '';
170181
foreach ($this->yieldParentBlock($name, $context, $blocks) as $data) {
171182
$content .= $data;
@@ -189,6 +200,26 @@ public function renderParentBlock($name, array $context, array $blocks = [])
189200
*/
190201
public function renderBlock($name, array $context, array $blocks = [], $useBlocks = true)
191202
{
203+
if (!$this->useYield) {
204+
$level = ob_get_level();
205+
if ($this->env->isDebug()) {
206+
ob_start();
207+
} else {
208+
ob_start(function () { return ''; });
209+
}
210+
try {
211+
$this->displayBlock($name, $context, $blocks, $useBlocks);
212+
} catch (\Throwable $e) {
213+
while (ob_get_level() > $level) {
214+
ob_end_clean();
215+
}
216+
217+
throw $e;
218+
}
219+
220+
return ob_get_clean();
221+
}
222+
192223
$content = '';
193224
foreach ($this->yieldBlock($name, $context, $blocks, $useBlocks) as $data) {
194225
$content .= $data;
@@ -331,6 +362,26 @@ public function display(array $context, array $blocks = []): void
331362

332363
public function render(array $context): string
333364
{
365+
if (!$this->useYield) {
366+
$level = ob_get_level();
367+
if ($this->env->isDebug()) {
368+
ob_start();
369+
} else {
370+
ob_start(function () { return ''; });
371+
}
372+
try {
373+
$this->display($context);
374+
} catch (\Throwable $e) {
375+
while (ob_get_level() > $level) {
376+
ob_end_clean();
377+
}
378+
379+
throw $e;
380+
}
381+
382+
return ob_get_clean();
383+
}
384+
334385
$content = '';
335386
foreach ($this->yield($context) as $data) {
336387
$content .= $data;
@@ -348,27 +399,7 @@ public function yield(array $context, array $blocks = []): iterable
348399
$blocks = array_merge($this->blocks, $blocks);
349400

350401
try {
351-
if ($this->useYield) {
352-
yield from $this->doDisplay($context, $blocks);
353-
354-
return;
355-
}
356-
357-
$level = ob_get_level();
358-
ob_start();
359-
360-
foreach ($this->doDisplay($context, $blocks) as $data) {
361-
if (ob_get_length()) {
362-
$data = ob_get_clean().$data;
363-
ob_start();
364-
}
365-
366-
yield $data;
367-
}
368-
369-
if (ob_get_length()) {
370-
yield ob_get_clean();
371-
}
402+
yield from $this->doDisplay($context, $blocks);
372403
} catch (Error $e) {
373404
if (!$e->getSourceContext()) {
374405
$e->setSourceContext($this->getSourceContext());
@@ -386,12 +417,6 @@ public function yield(array $context, array $blocks = []): iterable
386417
$e->guess();
387418

388419
throw $e;
389-
} finally {
390-
if (!$this->useYield) {
391-
while (ob_get_level() > $level) {
392-
ob_end_clean();
393-
}
394-
}
395420
}
396421
}
397422

@@ -418,27 +443,7 @@ public function yieldBlock($name, array $context, array $blocks = [], $useBlocks
418443

419444
if (null !== $template) {
420445
try {
421-
if ($this->useYield) {
422-
yield from $template->$block($context, $blocks);
423-
424-
return;
425-
}
426-
427-
$level = ob_get_level();
428-
ob_start();
429-
430-
foreach ($template->$block($context, $blocks) as $data) {
431-
if (ob_get_length()) {
432-
$data = ob_get_clean().$data;
433-
ob_start();
434-
}
435-
436-
yield $data;
437-
}
438-
439-
if (ob_get_length()) {
440-
yield ob_get_clean();
441-
}
446+
yield from $template->$block($context, $blocks);
442447
} catch (Error $e) {
443448
if (!$e->getSourceContext()) {
444449
$e->setSourceContext($template->getSourceContext());
@@ -456,12 +461,6 @@ public function yieldBlock($name, array $context, array $blocks = [], $useBlocks
456461
$e->guess();
457462

458463
throw $e;
459-
} finally {
460-
if (!$this->useYield) {
461-
while (ob_get_level() > $level) {
462-
ob_end_clean();
463-
}
464-
}
465464
}
466465
} elseif ($parent = $this->getParent($context)) {
467466
yield from $parent->unwrap()->yieldBlock($name, $context, array_merge($this->blocks, $blocks), false, $templateContext ?? $this);

0 commit comments

Comments
 (0)