Skip to content

Commit ae62dfa

Browse files
committed
BlueScreen: fixed PHP 8.4 exception in generator [Closes: nette#595]
1 parent 32303e0 commit ae62dfa

File tree

3 files changed

+162
-1
lines changed

3 files changed

+162
-1
lines changed

src/Tracy/BlueScreen/BlueScreen.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,12 @@ private function findGeneratorsAndFibers(object $object): array
483483
$add = function ($obj) use (&$generators, &$fibers) {
484484
if ($obj instanceof \Generator) {
485485
try {
486-
new \ReflectionGenerator($obj);
486+
$ref = new \ReflectionGenerator($obj);
487+
// Before PHP 8.4 the ReflectionGenerator cannot be constructed from closed generator.
488+
// Since PHP 8.4 it can, but getTrace throws ReflectionException.
489+
if (PHP_VERSION_ID >= 80400 && $ref->isClosed()) {
490+
return;
491+
}
487492
$generators[spl_object_id($obj)] = $obj;
488493
} catch (\ReflectionException) {
489494
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
/**
4+
* Test: Tracy\Debugger exception in generator in HTML.
5+
* @phpVersion 8.1 ReflectionGenerator::getTrace() is empty in PHP < 8.1
6+
* @httpCode 500
7+
* @exitCode 255
8+
* @outputMatchFile expected/Debugger.exception.in-generator.html.expect
9+
*/
10+
11+
declare(strict_types=1);
12+
13+
use Tracy\Debugger;
14+
15+
require __DIR__ . '/../bootstrap.php';
16+
17+
if (PHP_SAPI === 'cli') {
18+
Tester\Environment::skip('Debugger Bluescreen is not rendered in CLI mode');
19+
}
20+
21+
22+
Debugger::$productionMode = false;
23+
setHtmlMode();
24+
25+
Debugger::enable();
26+
27+
28+
$generator = (function (): iterable {
29+
yield 5;
30+
throw new Exception('The my exception', 123);
31+
})();
32+
$fn = function ($generator) {
33+
foreach ($generator as $value) {
34+
}
35+
};
36+
37+
$fn($generator);
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
<!DOCTYPE html><!-- "' --></textarea></script></style></pre></xmp></a></iframe></noembed></noframes></noscript></option></select></template></title></table></p></code>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="robots" content="noindex">
6+
<meta name="generator" content="Tracy by Nette Framework">
7+
8+
<title>Exception: The my exception #123</title>
9+
<!-- in %a%:%d% -->
10+
<!-- %a% -->
11+
12+
%A%
13+
</head>
14+
15+
16+
<body>
17+
<tracy-div id="tracy-bs" itemscope>
18+
<a id="tracy-bs-toggle" href="#" class="tracy-toggle">&#xfeff;</a>
19+
<div class="tracy-bs-main">
20+
<section class="tracy-section tracy-section--error">
21+
<p>Exception #123</p>
22+
23+
<h1><span>The my exception</span>
24+
<a href="%a%" class="tracy-action" target="_blank" rel="noreferrer noopener">search&#x25ba;</a>
25+
</h1>
26+
27+
</section>
28+
29+
30+
31+
<section class="tracy-section">
32+
<h2 class="tracy-section-label"><a href="#" data-tracy-ref="^+" class="tracy-toggle">Source file</a></h2>
33+
34+
<div class="tracy-section-panel">
35+
<p><b>File:</b> <a href="%a%" title="%a%" class="tracy-editor">%a%<b>Debugger.exception.in-generator.html.phpt</b>:%d%</a></p>
36+
<pre title="Ctrl-Click to open in editor" data-tracy-href="%a%" class='tracy-code'><div><code><span class='tracy-code-keyword'><span class='tracy-line'>%d%:</span>
37+
<span class='tracy-line'>%d%:</span>
38+
<span class='tracy-line'>%d%:</span> </span>Debugger<span class='tracy-code-keyword'>::</span><span class='tracy-code-var'>$productionMode </span><span class='tracy-code-keyword'>= </span>false<span class='tracy-code-keyword'>;
39+
<span class='tracy-line'>%d%:</span> </span>setHtmlMode<span class='tracy-code-keyword'>();
40+
<span class='tracy-line'>%d%:</span>
41+
<span class='tracy-line'>%d%:</span> </span>Debugger<span class='tracy-code-keyword'>::</span>enable<span class='tracy-code-keyword'>();
42+
<span class='tracy-line'>%d%:</span>
43+
<span class='tracy-line'>%d%:</span>
44+
<span class='tracy-line'>%d%:</span> </span><span class='tracy-code-var'>$generator </span><span class='tracy-code-keyword'>= (function (): </span>iterable <span class='tracy-code-keyword'>{
45+
<span class='tracy-line'>%d%:</span> yield </span><span class='tracy-dump-number'>5</span><span class='tracy-code-keyword'>;
46+
</span><span class='tracy-line-highlight'>%d%: throw new Exception('The my exception', 123);</span>
47+
<span class='tracy-code-keyword'><span class='tracy-line'>%d%:</span> })();
48+
<span class='tracy-line'>%d%:</span> </span><span class='tracy-code-var'>$fn </span><span class='tracy-code-keyword'>= function (</span><span class='tracy-code-var'>$generator</span><span class='tracy-code-keyword'>) {
49+
<span class='tracy-line'>%d%:</span> foreach (</span><span class='tracy-code-var'>$generator </span><span class='tracy-code-keyword'>as </span><span class='tracy-code-var'>$value</span><span class='tracy-code-keyword'>) {
50+
<span class='tracy-line'>%d%:</span> }
51+
</span></code></div></pre>
52+
</div>
53+
</section>
54+
55+
<section class="tracy-section">
56+
<h2 class="tracy-section-label"><a href="#" data-tracy-ref="^+" class="tracy-toggle">Call stack</a></h2>
57+
58+
<div class="tracy-section-panel">
59+
<div class="tracy-callstack">
60+
61+
<div class="tracy-callstack-file">
62+
<a href="%a%" title="%a%" class="tracy-editor">%a%<b>Debugger.exception.in-generator.html.phpt</b>:%d%</a>
63+
</div>
64+
65+
<div class="tracy-callstack-callee">
66+
<a href="#" data-tracy-ref="^div + div" class="tracy-toggle tracy-collapsed"><b>{closure%a?%}</b> ()</a>
67+
</div>
68+
69+
<div class="tracy-callstack-additional tracy-collapsed">
70+
<pre title="Ctrl-Click to open in editor" data-tracy-href="%a%" class='tracy-code'><div><code><span class='tracy-code-keyword'><span class='tracy-line'>%d%:</span> </span>setHtmlMode<span class='tracy-code-keyword'>();
71+
<span class='tracy-line'>%d%:</span>
72+
<span class='tracy-line'>%d%:</span> </span>Debugger<span class='tracy-code-keyword'>::</span>enable<span class='tracy-code-keyword'>();
73+
<span class='tracy-line'>%d%:</span>
74+
<span class='tracy-line'>%d%:</span>
75+
<span class='tracy-line'>%d%:</span> </span><span class='tracy-code-var'>$generator </span><span class='tracy-code-keyword'>= (function (): </span>iterable <span class='tracy-code-keyword'>{
76+
<span class='tracy-line'>%d%:</span> yield </span><span class='tracy-dump-number'>5</span><span class='tracy-code-keyword'>;
77+
<span class='tracy-line'>%d%:</span> throw new </span>Exception<span class='tracy-code-keyword'>(</span><span class='tracy-dump-string'>'The my exception'</span><span class='tracy-code-keyword'>, </span><span class='tracy-dump-number'>123</span><span class='tracy-code-keyword'>);
78+
<span class='tracy-line'>%d%:</span> })();
79+
<span class='tracy-line'>%d%:</span> </span><span class='tracy-code-var'>$fn </span><span class='tracy-code-keyword'>= function (</span><span class='tracy-code-var'>$generator</span><span class='tracy-code-keyword'>) {
80+
</span><span class='tracy-line-highlight'>%d%: foreach ($generator as $value) {</span>
81+
<span class='tracy-code-keyword'><span class='tracy-line'>%d%:</span> }
82+
<span class='tracy-line'>%d%:</span> };
83+
<span class='tracy-line'>%d%:</span>
84+
<span class='tracy-line'>%d%:</span> </span><span class='tracy-code-var'>$fn</span><span class='tracy-code-keyword'>(</span><span class='tracy-code-var'>$generator</span><span class='tracy-code-keyword'>);</span>
85+
</code></div></pre>
86+
87+
</div>
88+
89+
<div class="tracy-callstack-file">
90+
<a href="%a%" title="%a%" class="tracy-editor">%a%<b>Debugger.exception.in-generator.html.phpt</b>:%d%</a>
91+
</div>
92+
93+
<div class="tracy-callstack-callee">
94+
<a href="#" data-tracy-ref="^div + div" class="tracy-toggle tracy-collapsed"><b>{closure%a?%}</b> (...)</a>
95+
</div>
96+
97+
<div class="tracy-callstack-additional tracy-collapsed">
98+
<pre title="Ctrl-Click to open in editor" data-tracy-href="%a%" class='tracy-code'><div><code><span class='tracy-code-keyword'><span class='tracy-line'>%d%:</span>
99+
<span class='tracy-line'>%d%:</span> </span><span class='tracy-code-var'>$generator </span><span class='tracy-code-keyword'>= (function (): </span>iterable <span class='tracy-code-keyword'>{
100+
<span class='tracy-line'>%d%:</span> yield </span><span class='tracy-dump-number'>5</span><span class='tracy-code-keyword'>;
101+
<span class='tracy-line'>%d%:</span> throw new </span>Exception<span class='tracy-code-keyword'>(</span><span class='tracy-dump-string'>'The my exception'</span><span class='tracy-code-keyword'>, </span><span class='tracy-dump-number'>123</span><span class='tracy-code-keyword'>);
102+
<span class='tracy-line'>%d%:</span> })();
103+
<span class='tracy-line'>%d%:</span> </span><span class='tracy-code-var'>$fn </span><span class='tracy-code-keyword'>= function (</span><span class='tracy-code-var'>$generator</span><span class='tracy-code-keyword'>) {
104+
<span class='tracy-line'>%d%:</span> foreach (</span><span class='tracy-code-var'>$generator </span><span class='tracy-code-keyword'>as </span><span class='tracy-code-var'>$value</span><span class='tracy-code-keyword'>) {
105+
<span class='tracy-line'>%d%:</span> }
106+
<span class='tracy-line'>%d%:</span> };
107+
<span class='tracy-line'>%d%:</span>
108+
</span><span class='tracy-line-highlight'>%d%: $fn($generator);</span>
109+
</code></div></pre>
110+
111+
<table class="tracy-callstack-args">
112+
<tr><th>#0</th><td><pre class="tracy-dump tracy-light" data-tracy-dump='%a%'></pre>
113+
</td></tr>
114+
</table>
115+
</div>
116+
</div>
117+
</div>
118+
</section>
119+
%A%

0 commit comments

Comments
 (0)