diff --git a/src/Frame.php b/src/Frame.php index fa5b3e169..11a632120 100644 --- a/src/Frame.php +++ b/src/Frame.php @@ -13,6 +13,9 @@ final class Frame { public const INTERNAL_FRAME_FILENAME = '[internal]'; + /** + * @deprecated This constant is deprecated and will be removed in 5.x. + */ public const ANONYMOUS_CLASS_PREFIX = "class@anonymous\x00"; /** diff --git a/src/FrameBuilder.php b/src/FrameBuilder.php index 1eec712d4..71f82024f 100644 --- a/src/FrameBuilder.php +++ b/src/FrameBuilder.php @@ -74,8 +74,15 @@ public function buildFromBacktraceFrame(string $file, int $line, array $backtrac if (isset($backtraceFrame['class']) && isset($backtraceFrame['function'])) { $functionName = $backtraceFrame['class']; - if (mb_substr($functionName, 0, mb_strlen(Frame::ANONYMOUS_CLASS_PREFIX)) === Frame::ANONYMOUS_CLASS_PREFIX) { - $functionName = Frame::ANONYMOUS_CLASS_PREFIX . $this->stripPrefixFromFilePath($this->options, substr($backtraceFrame['class'], \strlen(Frame::ANONYMOUS_CLASS_PREFIX))); + // Optimization: skip doing regex if we don't have prefixes to strip + if ($this->options->getPrefixes()) { + $prefixStrippedFunctionName = preg_replace_callback('/@anonymous\\x00([^:]+)(:.*)?/', function (array $matches) { + return "@anonymous\x00" . $this->stripPrefixFromFilePath($this->options, $matches[1]) . ($matches[2] ?? ''); + }, $functionName); + + if ($prefixStrippedFunctionName) { + $functionName = $prefixStrippedFunctionName; + } } $rawFunctionName = \sprintf('%s::%s', $backtraceFrame['class'], $backtraceFrame['function']); diff --git a/tests/FrameBuilderTest.php b/tests/FrameBuilderTest.php index ebaa58df8..c9393f5b1 100644 --- a/tests/FrameBuilderTest.php +++ b/tests/FrameBuilderTest.php @@ -149,6 +149,19 @@ public static function buildFromBacktraceFrameDataProvider(): \Generator ], new Frame(null, 'path/not/of/app/to/file', 10, null, 'path/not/of/app/to/file'), ]; + + yield [ + new Options([ + 'prefixes' => ['/path/to'], + ]), + [ + 'file' => '/path/to/file', + 'line' => 10, + 'function' => 'test_function', + 'class' => "App\\ClassName@anonymous\0/path/to/file:85$29e", + ], + new Frame("App\\ClassName@anonymous\0/file::test_function", '/file', 10, "App\\ClassName@anonymous\0/path/to/file:85$29e::test_function", '/path/to/file'), + ]; } /**