From ae62dfa5a41c88a5d203cc8fc250c8612bcab577 Mon Sep 17 00:00:00 2001
From: schlndh
Date: Sun, 11 May 2025 09:56:16 +0200
Subject: [PATCH] BlueScreen: fixed PHP 8.4 exception in generator [Closes:
#595]
---
src/Tracy/BlueScreen/BlueScreen.php | 7 +-
.../Debugger.exception.in-generator.html.phpt | 37 ++++++
...ebugger.exception.in-generator.html.expect | 119 ++++++++++++++++++
3 files changed, 162 insertions(+), 1 deletion(-)
create mode 100644 tests/Tracy/Debugger.exception.in-generator.html.phpt
create mode 100644 tests/Tracy/expected/Debugger.exception.in-generator.html.expect
diff --git a/src/Tracy/BlueScreen/BlueScreen.php b/src/Tracy/BlueScreen/BlueScreen.php
index acdae1e4a..cc1c51a4a 100644
--- a/src/Tracy/BlueScreen/BlueScreen.php
+++ b/src/Tracy/BlueScreen/BlueScreen.php
@@ -483,7 +483,12 @@ private function findGeneratorsAndFibers(object $object): array
$add = function ($obj) use (&$generators, &$fibers) {
if ($obj instanceof \Generator) {
try {
- new \ReflectionGenerator($obj);
+ $ref = new \ReflectionGenerator($obj);
+ // Before PHP 8.4 the ReflectionGenerator cannot be constructed from closed generator.
+ // Since PHP 8.4 it can, but getTrace throws ReflectionException.
+ if (PHP_VERSION_ID >= 80400 && $ref->isClosed()) {
+ return;
+ }
$generators[spl_object_id($obj)] = $obj;
} catch (\ReflectionException) {
}
diff --git a/tests/Tracy/Debugger.exception.in-generator.html.phpt b/tests/Tracy/Debugger.exception.in-generator.html.phpt
new file mode 100644
index 000000000..1d3b2d4ce
--- /dev/null
+++ b/tests/Tracy/Debugger.exception.in-generator.html.phpt
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+ Exception: The my exception #123
+
+
+
+ %A%
+
+
+
+
+
+
+
+
+ Exception #123
+
+ The my exception
+ search►
+
+
+
+
+
+
+
+
+
+
+
File: %a%Debugger.exception.in-generator.html.phpt:%d%
+
%d%:
+%d%:
+%d%: Debugger::$productionMode = false;
+%d%: setHtmlMode();
+%d%:
+%d%: Debugger::enable();
+%d%:
+%d%:
+%d%: $generator = (function (): iterable {
+%d%: yield 5;
+%d%: throw new Exception('The my exception', 123);
+%d%: })();
+%d%: $fn = function ($generator) {
+%d%: foreach ($generator as $value) {
+%d%: }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
%d%: setHtmlMode();
+%d%:
+%d%: Debugger::enable();
+%d%:
+%d%:
+%d%: $generator = (function (): iterable {
+%d%: yield 5;
+%d%: throw new Exception('The my exception', 123);
+%d%: })();
+%d%: $fn = function ($generator) {
+%d%: foreach ($generator as $value) {
+%d%: }
+%d%: };
+%d%:
+%d%: $fn($generator);
+
+
+
+
+
+
+
+
+
+
%d%:
+%d%: $generator = (function (): iterable {
+%d%: yield 5;
+%d%: throw new Exception('The my exception', 123);
+%d%: })();
+%d%: $fn = function ($generator) {
+%d%: foreach ($generator as $value) {
+%d%: }
+%d%: };
+%d%:
+%d%: $fn($generator);
+
+
+
+
+
+
+
+%A%