diff --git a/examples/xdebug.php b/examples/xdebug.php new file mode 100644 index 000000000..2282d9203 --- /dev/null +++ b/examples/xdebug.php @@ -0,0 +1,66 @@ + + + +

Tracy: exception demo

+ +second(); + } + + + public function second() + { + self::third([1, 2, 3]); + } + + + public static function third($arg5) + { + //require __DIR__ . '/assets/E_COMPILE_WARNING-1.php'; + //require __DIR__ . '/assets/E_COMPILE_ERROR.php'; +// trigger_error('jo', E_USER_ERROR); +// dump(new Exception); +// dumpe(xdebug_get_function_stack( [ 'local_vars' => true, 'params_as_values' => true ] )); + try { + throw new Exception('Original'); + } catch (Exception $e) { + throw new Exception('The my exception', 123, $e); + } + $a++; + } +} + + + +function demo($a, $b) +{ + $demo = new DemoClass; + $demo->first($a, $b); +} + + +if (Debugger::$productionMode) { + echo '

For security reasons, Tracy is visible only on localhost. Look into the source code to see how to enable Tracy.

'; +} + +demo(10, 'any string'); diff --git a/src/Tracy/BlueScreen/BlueScreen.php b/src/Tracy/BlueScreen/BlueScreen.php index 656058d67..fb220a05b 100644 --- a/src/Tracy/BlueScreen/BlueScreen.php +++ b/src/Tracy/BlueScreen/BlueScreen.php @@ -499,4 +499,18 @@ private function findGeneratorsAndFibers(object $object): array Helpers::traverseValue($object, $add); return [$generators, $fibers]; } + + + public function getRealArgsAndVariables(\Throwable $exception): array + { + $args = $variables = []; + if (function_exists('xdebug_get_function_stack') && version_compare(phpversion('xdebug'), '3.3.0', '>=')) { + $stack = xdebug_get_function_stack(['from_exception' => $exception]); + foreach (array_reverse($stack) as $k => $row) { + $args[$k] = $row['params'] ?? []; + $variables[$k - 1] = $row['variables'] ?? []; + } + } + return [$args, $variables]; + } } diff --git a/src/Tracy/BlueScreen/assets/bluescreen.css b/src/Tracy/BlueScreen/assets/bluescreen.css index bbe86c943..f63c29569 100644 --- a/src/Tracy/BlueScreen/assets/bluescreen.css +++ b/src/Tracy/BlueScreen/assets/bluescreen.css @@ -350,11 +350,15 @@ html.tracy-bs-visible body { grid-column-end: 3; } -#tracy-bs .tracy-callstack-args tr:first-child > * { +#tracy-bs .tracy-callstack-args tr > :first-child { + width: 10em; +} + +#tracy-bs .tracy-callstack-args-warning tr:first-child > * { position: relative; } -#tracy-bs .tracy-callstack-args tr:first-child td:before { +#tracy-bs .tracy-callstack-args-warning tr:first-child td:before { position: absolute; right: .3em; content: 'may not be true'; diff --git a/src/Tracy/BlueScreen/assets/section-stack-callStack.phtml b/src/Tracy/BlueScreen/assets/section-stack-callStack.phtml index 74b3744d8..130dfa087 100644 --- a/src/Tracy/BlueScreen/assets/section-stack-callStack.phtml +++ b/src/Tracy/BlueScreen/assets/section-stack-callStack.phtml @@ -8,6 +8,8 @@ namespace Tracy; * @var callable $dump * @var int $expanded * @var array $stack + * @var ?array $realArgs + * @var ?array $variables */ if (!$stack) { @@ -66,8 +68,19 @@ if (!$stack) { - + + $v) { + echo '\n"; + } +?> +
', Helpers::escapeHtml((is_string($argName) ? '$' : '#') . $argName), ''; + echo $dump($v, $argName); + echo "
+ + +
+ + +

Local Variables

+ + + $v) { + echo '\n"; + } +?> +
$', Helpers::escapeHtml($k), ''; + echo $dump($v, $k); + echo "
+ diff --git a/src/Tracy/BlueScreen/assets/section-stack-exception.phtml b/src/Tracy/BlueScreen/assets/section-stack-exception.phtml index 9e9bc66de..e3d459832 100644 --- a/src/Tracy/BlueScreen/assets/section-stack-exception.phtml +++ b/src/Tracy/BlueScreen/assets/section-stack-exception.phtml @@ -33,6 +33,8 @@ if (($stack[0]['class'] ?? null) === Debugger::class && in_array($stack[0]['func } $file = $ex->getFile(); $line = $ex->getLine(); +[$realArgs, $variables] = $this->getRealArgsAndVariables($ex); require __DIR__ . '/section-stack-sourceFile.phtml'; +require __DIR__ . '/section-stack-variables.phtml'; require __DIR__ . '/section-stack-callStack.phtml'; diff --git a/src/Tracy/BlueScreen/assets/section-stack-variables.phtml b/src/Tracy/BlueScreen/assets/section-stack-variables.phtml new file mode 100644 index 000000000..6fc766421 --- /dev/null +++ b/src/Tracy/BlueScreen/assets/section-stack-variables.phtml @@ -0,0 +1,30 @@ + + +
+

Local variables

+ +
+ + $v) { + echo '\n"; + } +?> +
$', Helpers::escapeHtml($k), ''; + echo $dump($v, $k); + echo "
+
+
diff --git a/src/Tracy/Dumper/Describer.php b/src/Tracy/Dumper/Describer.php index e841a3fa4..a0d293c68 100644 --- a/src/Tracy/Dumper/Describer.php +++ b/src/Tracy/Dumper/Describer.php @@ -326,19 +326,19 @@ private static function findLocation(): ?array if (isset($item['class']) && ($item['class'] === self::class || $item['class'] === Tracy\Dumper::class)) { $location = $item; continue; - } elseif (isset($item['function'])) { - try { - $reflection = isset($item['class']) - ? new \ReflectionMethod($item['class'], $item['function']) - : new \ReflectionFunction($item['function']); - if ( - $reflection->isInternal() - || preg_match('#\s@tracySkipLocation\s#', (string) $reflection->getDocComment()) - ) { - $location = $item; - continue; - } - } catch (\ReflectionException) { + } elseif ( + isset($item['function']) + && (isset($item['class']) ? method_exists($item['class'], $item['function']) : function_exists($item['function'])) + ) { + $reflection = isset($item['class']) + ? new \ReflectionMethod($item['class'], $item['function']) + : new \ReflectionFunction($item['function']); + if ( + $reflection->isInternal() + || preg_match('#\s@tracySkipLocation\s#', (string) $reflection->getDocComment()) + ) { + $location = $item; + continue; } }