protected function getFrames() : array
    {
        $frames = $this->throwable->getTrace();

        if (!$this->throwable instanceof \ErrorException) {

            // Make sure the first frame in the trace actually points to the Throwable we're inspecting.
            array_unshift($frames, diagnostics\Debug::throwableToArray($this->throwable));

            return $frames;
        }

        // We're going to determine if the exception in fact stems from an irrecoverable fatal error.
        $fatal = false;

        // Note: E_RECOVERABLE_ERROR and E_PARSE should as of PHP7 be entirely converted to Throwables
        // so they should be caught by an Exception Handler directly instead of first going through an Error Handler
        // and being converted to an Error Exception, let alone a FatalError Exception. We still keep
        // them here for edge cases, however.
        switch ($this->throwable->getSeverity()) {
            case E_ERROR:
            case E_CORE_ERROR:
            case E_COMPILE_ERROR:
            case E_USER_ERROR:
            case E_RECOVERABLE_ERROR:
            case E_PARSE:
                $fatal = true;
            break;
        }

        // Without XDebug we don't actually have any means to determine the stacktrace of a fatal error.
        if (!$fatal || !extension_loaded('xdebug') || !xdebug_is_enabled()) {
            // Our error handler will be the first frame in the trace since it's the one which converted
            // the error to an exception. We're gonna copy over the context and remove
            // Remove our (error) handler from the stack trace (it's otherwise always going to occlude
            // the actual exception).
            // $frames[1]['args'] = $frames[0]['args'];
            array_shift($frames);

            return $frames;
        }

        // Remove our internal handling logic from the stack trace so it doesn't occlude the actual trace.
        $frames = array_diff_key(array_reverse(xdebug_get_function_stack()), debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS));

        // Handle some potential inconsistencies between XDebug and the way we want to handle things.
        foreach ($frames as &$frame) {

            if ('dynamic' === $frame['type']) {
                $frame['type'] = '->';
            } elseif ('static' === $frame['type']) {
                $frame['type'] = '::';
            }

            // XDebug uses a different key for the args array.
            if (isset($frame['params']) && !isset($frame['args'])) {
                $frame['args'] = $frame['params'];
                unset($frame['params']);
            }
        }

        return $frames;
    }