Skip to content

Commit

Permalink
BlueScreen: added panels for Generator & Fiber
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Apr 28, 2022
1 parent 1896bf0 commit d6261b5
Show file tree
Hide file tree
Showing 18 changed files with 662 additions and 28 deletions.
43 changes: 43 additions & 0 deletions src/Tracy/BlueScreen/BlueScreen.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,17 @@ class BlueScreen
/** @var array */
private $snapshot;

/** @var \WeakMap<\Fiber|\Generator> */
private $fibers;


public function __construct()
{
$this->collapsePaths = preg_match('#(.+/vendor)/tracy/tracy/src/Tracy/BlueScreen$#', strtr(__DIR__, '\\', '/'), $m)
? [$m[1] . '/tracy', $m[1] . '/nette', $m[1] . '/latte']
: [dirname(__DIR__)];
$this->fileGenerators[] = [self::class, 'generateNewPhpFileContents'];
$this->fibers = PHP_VERSION_ID < 80000 ? new \SplObjectStorage : new \WeakMap;
}


Expand Down Expand Up @@ -100,6 +104,17 @@ public function addFileGenerator(callable $generator): self
}


/**
* @param \Fiber|\Generator $fiber
* @return static
*/
public function addFiber($fiber): self
{
$this->fibers[$fiber] = true;
return $this;
}


/**
* Renders blue screen.
*/
Expand Down Expand Up @@ -143,6 +158,7 @@ public function renderToFile(\Throwable $exception, string $file): bool

private function renderTemplate(\Throwable $exception, string $template, $toScreen = true): void
{
[$generators, $fibers] = $this->findGeneratorsAndFibers($exception);
$headersSent = headers_sent($headersFile, $headersLine);
$obStatus = Debugger::$obStatus;
$showEnvironment = $this->showEnvironment && (strpos($exception->getMessage(), 'Allowed memory size') === false);
Expand Down Expand Up @@ -576,4 +592,31 @@ public static function generateNewPhpFileContents(string $file, ?string $class =

return $res . "class $class\n{\n\$END\$\n}\n";
}


private function findGeneratorsAndFibers(object $object): array
{
$generators = $fibers = [];
$add = function ($obj) use (&$generators, &$fibers) {
if ($obj instanceof \Generator) {
try {
new \ReflectionGenerator($obj);
$generators[spl_object_id($obj)] = $obj;
} catch (\ReflectionException $e) {
}
} elseif ($obj instanceof \Fiber && $obj->isStarted() && !$obj->isTerminated()) {
$fibers[spl_object_id($obj)] = $obj;
}
};

foreach ($this->fibers as $obj => $foo) {
$add($obj);
}

if (PHP_VERSION_ID >= 80000) {
Helpers::traverseValue($object, $add);
}

return [$generators, $fibers];
}
}
4 changes: 4 additions & 0 deletions src/Tracy/BlueScreen/assets/bluescreen.css
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,10 @@
background: #cd1818a6;
}

#tracy-bs .tracy-section--error + .tracy-section--stack {
margin-top: calc(1.5 * var(--tracy-space));
}


/* tabs */
#tracy-bs .tracy-tab-bar {
Expand Down
2 changes: 2 additions & 0 deletions src/Tracy/BlueScreen/assets/content.phtml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ namespace Tracy;
* @var ?string $headersFile
* @var ?int $headersLine
* @var ?array $obStatus
* @var \Generator[] $generators
* @var \Fiber[] $fibers
*/
?>
<tracy-div id="tracy-bs" itemscope>
Expand Down
63 changes: 40 additions & 23 deletions src/Tracy/BlueScreen/assets/section-exception.phtml
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,10 @@ namespace Tracy;
* @var array[] $actions
* @var callable $dump
* @var BlueScreen $this
* @var \Generator[] $generators
* @var \Fiber[] $fibers
*/

$stack = $ex->getTrace();
$expanded = null;
if (
(!$ex instanceof \ErrorException
|| in_array($ex->getSeverity(), [E_USER_NOTICE, E_USER_WARNING, E_USER_DEPRECATED], true))
&& $this->isCollapsed($ex->getFile())
) {
foreach ($stack as $key => $row) {
if (isset($row['file']) && !$this->isCollapsed($row['file'])) {
$expanded = $key;
break;
}
}
}

if (in_array($stack[0]['class'] ?? null, [DevelopmentStrategy::class, ProductionStrategy::class], true)) {
array_shift($stack);
}
if (($stack[0]['class'] ?? null) === Debugger::class && in_array($stack[0]['function'], ['shutdownHandler', 'errorHandler'], true)) {
array_shift($stack);
}
?>
<?php require __DIR__ . '/section-header.phtml' ?>

Expand All @@ -46,9 +27,45 @@ if (($stack[0]['class'] ?? null) === Debugger::class && in_array($stack[0]['func
</section>
<?php endforeach ?>

<?php require __DIR__ . '/section-exception-sourceFile.phtml' ?>
<?php if (!$exceptions && ($generators || $fibers)): ?>
<section class="tracy-section tracy-section--stack">
<div class="tracy-section-panel">
<div class="tracy-tabs">
<ul class="tracy-tab-bar">
<li class="tracy-tab-label tracy-active"><a href="#">Main thread</a></li>

<?php foreach ($generators as $id => $generator): ?>
<li class="tracy-tab-label"><a href="#">Generator #<?= $id ?></a></li>
<?php endforeach ?>

<?php foreach ($fibers as $id => $fiber): ?>
<li class="tracy-tab-label"><a href="#">Fiber #<?= $id ?></a></li>
<?php endforeach ?>
</ul>

<div>
<div class="tracy-tab-panel tracy-active">
<?php require __DIR__ . '/section-stack-exception.phtml' ?>
</div>

<?php require __DIR__ . '/section-exception-callStack.phtml' ?>
<?php foreach ($generators as $generator): ?>
<div class="tracy-tab-panel">
<?php require __DIR__ . '/section-stack-generator.phtml' ?>
</div>
<?php endforeach ?>

<?php foreach ($fibers as $fiber): ?>
<div class="tracy-tab-panel">
<?php require __DIR__ . '/section-stack-fiber.phtml' ?>
</div>
<?php endforeach ?>
</div>
</div>
</div>
</section>
<?php else: ?>
<?php require __DIR__ . '/section-stack-exception.phtml' ?>
<?php endif ?>

<?php require __DIR__ . '/section-exception-variables.phtml' ?>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ declare(strict_types=1);
namespace Tracy;

/**
* @var \Throwable $ex
* @var callable $dump
* @var int $expanded
* @var array $stack
Expand All @@ -15,6 +14,7 @@ if (!$stack) {
return;
}
?>

<section class="tracy-section">
<h2 class="tracy-section-label"><a href="#" data-tracy-ref="^+" class="tracy-toggle">Call stack</a></h2>

Expand Down
38 changes: 38 additions & 0 deletions src/Tracy/BlueScreen/assets/section-stack-exception.phtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace Tracy;

/**
* @var \Throwable $ex
* @var callable $dump
* @var BlueScreen $this
*/

$stack = $ex->getTrace();
$expanded = null;
if (
(!$ex instanceof \ErrorException
|| in_array($ex->getSeverity(), [E_USER_NOTICE, E_USER_WARNING, E_USER_DEPRECATED], true))
&& $this->isCollapsed($ex->getFile())
) {
foreach ($stack as $key => $row) {
if (isset($row['file']) && !$this->isCollapsed($row['file'])) {
$expanded = $key;
break;
}
}
}

if (in_array($stack[0]['class'] ?? null, [DevelopmentStrategy::class, ProductionStrategy::class], true)) {
array_shift($stack);
}
if (($stack[0]['class'] ?? null) === Debugger::class && in_array($stack[0]['function'], ['shutdownHandler', 'errorHandler'], true)) {
array_shift($stack);
}
$file = $ex->getFile();
$line = $ex->getLine();

require __DIR__ . '/section-stack-sourceFile.phtml';
require __DIR__ . '/section-stack-callStack.phtml';
16 changes: 16 additions & 0 deletions src/Tracy/BlueScreen/assets/section-stack-fiber.phtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace Tracy;

/**
* @var \Fiber $fiber
* @var callable $dump
*/

$ref = new \ReflectionFiber($fiber);
$stack = $ref->getTrace();
$expanded = 0;

require __DIR__ . '/section-stack-callStack.phtml';
21 changes: 21 additions & 0 deletions src/Tracy/BlueScreen/assets/section-stack-generator.phtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace Tracy;

/**
* @var \Generator $generator
* @var callable $dump
*/

$ref = new \ReflectionGenerator($generator);
$stack = $ref->getTrace();
$expanded = null;
$execGenerator = $ref->getExecutingGenerator();
$refExec = new \ReflectionGenerator($execGenerator);
$file = $refExec->getExecutingFile();
$line = $refExec->getExecutingLine();

require __DIR__ . '/section-stack-sourceFile.phtml';
require __DIR__ . '/section-stack-callStack.phtml';
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ declare(strict_types=1);
namespace Tracy;

/**
* @var \Throwable $ex
* @var string $file
* @var int $line
* @var int $expanded
*/

$sourceOriginal = $ex->getFile() && is_file($ex->getFile()) ? [$ex->getFile(), $ex->getLine()] : null;
$sourceMapped = $sourceOriginal ? Debugger::mapSource(...$sourceOriginal) : null;
$sourceOriginal = $file && is_file($file) ? [$file, $line] : null;
$sourceMapped = $sourceOriginal ? Debugger::mapSource($file, $line) : null;
?>

<section class="tracy-section">
<h2 class="tracy-section-label"><a href="#" data-tracy-ref="^+" class="tracy-toggle<?= ($collapsed = $expanded !== null) ? ' tracy-collapsed' : '' ?>">Source file</a></h2>

Expand All @@ -36,7 +38,7 @@ $sourceMapped = $sourceOriginal ? Debugger::mapSource(...$sourceOriginal) : null
</div>
</div>
<?php else: ?>
<p><b>File:</b> <?= Helpers::editorLink($ex->getFile(), $ex->getLine()) ?></p>
<p><b>File:</b> <?= Helpers::editorLink($file, $line) ?></p>
<?php if ($sourceOriginal) echo BlueScreen::highlightFile(...$sourceOriginal) ?>
<?php endif ?>

Expand Down
26 changes: 26 additions & 0 deletions src/Tracy/Helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -591,4 +591,30 @@ public static function getExceptionChain(\Throwable $ex): array

return $res;
}


public static function traverseValue($val, callable $callback, array &$skip = [], ?string $refId = null): void
{
if (is_object($val)) {
$id = spl_object_id($val);
if (!isset($skip[$id])) {
$skip[$id] = true;
$callback($val);
self::traverseValue((array) $val, $callback, $skip);
}

} elseif (is_array($val)) {
if ($refId) {
if (isset($skip[$refId])) {
return;
}
$skip[$refId] = true;
}

foreach ($val as $k => $v) {
$refId = ($r = \ReflectionReference::fromArrayElement($val, $k)) ? $r->getId() : null;
self::traverseValue($v, $callback, $skip, $refId);
}
}
}
}
62 changes: 62 additions & 0 deletions tests/Tracy/Debugger.exception.fiber.html.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

/**
* Test: Tracy\Debugger exception in HTML.
* @phpVersion 8.1
* @httpCode 500
* @exitCode 255
* @outputMatchFile expected/Debugger.exception.fiber.html.expect
*/

declare(strict_types=1);

use Tracy\Debugger;

require __DIR__ . '/../bootstrap.php';

if (PHP_SAPI === 'cli') {
Tester\Environment::skip('Debugger Bluescreen is not rendered in CLI mode');
}


Debugger::$productionMode = false;
setHtmlMode();

Debugger::enable();


function gen1()
{
gen2(123);
}


function gen2($a)
{
$x = Fiber::suspend($a);
}


function first($arg1, $arg2)
{
second(true, false);
}


function second($arg1, $arg2)
{
third([1, 2, 3]);
}


function third($arg1)
{
throw new Exception('The my exception', 123);
}


$fiber = new Fiber(function () {
gen1();
});
$fiber->start();
first($fiber, 'any string');
Loading

0 comments on commit d6261b5

Please sign in to comment.