context.tsx 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. import styled from '@emotion/styled';
  2. import ClippedBox from 'sentry/components/clippedBox';
  3. import ErrorBoundary from 'sentry/components/errorBoundary';
  4. import {IconFlag} from 'sentry/icons';
  5. import {t} from 'sentry/locale';
  6. import space from 'sentry/styles/space';
  7. import {Frame, Organization, SentryAppComponent} from 'sentry/types';
  8. import {Event} from 'sentry/types/event';
  9. import {defined} from 'sentry/utils';
  10. import withOrganization from 'sentry/utils/withOrganization';
  11. import {parseAssembly} from '../utils';
  12. import {Assembly} from './assembly';
  13. import ContextLine from './contextLine';
  14. import {FrameRegisters} from './frameRegisters';
  15. import {FrameVariables} from './frameVariables';
  16. import {OpenInContextLine} from './openInContextLine';
  17. import StacktraceLink from './stacktraceLink';
  18. type Props = {
  19. components: Array<SentryAppComponent>;
  20. event: Event;
  21. frame: Frame;
  22. registers: {[key: string]: string};
  23. className?: string;
  24. emptySourceNotation?: boolean;
  25. expandable?: boolean;
  26. frameMeta?: Record<any, any>;
  27. hasAssembly?: boolean;
  28. hasContextRegisters?: boolean;
  29. hasContextSource?: boolean;
  30. hasContextVars?: boolean;
  31. isExpanded?: boolean;
  32. organization?: Organization;
  33. registersMeta?: Record<any, any>;
  34. };
  35. const Context = ({
  36. hasContextVars = false,
  37. hasContextSource = false,
  38. hasContextRegisters = false,
  39. isExpanded = false,
  40. hasAssembly = false,
  41. expandable = false,
  42. emptySourceNotation = false,
  43. registers,
  44. components,
  45. frame,
  46. event,
  47. organization,
  48. className,
  49. frameMeta,
  50. registersMeta,
  51. }: Props) => {
  52. if (!hasContextSource && !hasContextVars && !hasContextRegisters && !hasAssembly) {
  53. return emptySourceNotation ? (
  54. <div className="empty-context">
  55. <StyledIconFlag size="xs" />
  56. <p>{t('No additional details are available for this frame.')}</p>
  57. </div>
  58. ) : null;
  59. }
  60. const contextLines = isExpanded
  61. ? frame.context
  62. : frame.context.filter(l => l[0] === frame.lineNo);
  63. const startLineNo = hasContextSource ? frame.context[0][0] : undefined;
  64. return (
  65. <Wrapper
  66. start={startLineNo}
  67. className={`${className} context ${isExpanded ? 'expanded' : ''}`}
  68. >
  69. {defined(frame.errors) && (
  70. <li className={expandable ? 'expandable error' : 'error'} key="errors">
  71. {frame.errors.join(', ')}
  72. </li>
  73. )}
  74. {frame.context &&
  75. contextLines.map((line, index) => {
  76. const isActive = frame.lineNo === line[0];
  77. const hasComponents = isActive && components.length > 0;
  78. return (
  79. <StyledContextLine key={index} line={line} isActive={isActive}>
  80. {hasComponents && (
  81. <ErrorBoundary mini>
  82. <OpenInContextLine
  83. key={index}
  84. lineNo={line[0]}
  85. filename={frame.filename || ''}
  86. components={components}
  87. />
  88. </ErrorBoundary>
  89. )}
  90. {organization?.features.includes('integrations-stacktrace-link') &&
  91. isActive &&
  92. isExpanded &&
  93. frame.inApp &&
  94. frame.filename && (
  95. <ErrorBoundary customComponent={null}>
  96. <StacktraceLink
  97. key={index}
  98. lineNo={line[0]}
  99. frame={frame}
  100. event={event}
  101. />
  102. </ErrorBoundary>
  103. )}
  104. </StyledContextLine>
  105. );
  106. })}
  107. {hasContextVars && (
  108. <StyledClippedBox clipHeight={100}>
  109. <FrameVariables data={frame.vars ?? {}} meta={frameMeta?.vars} />
  110. </StyledClippedBox>
  111. )}
  112. {hasContextRegisters && (
  113. <FrameRegisters
  114. registers={registers}
  115. meta={registersMeta}
  116. deviceArch={event.contexts?.device?.arch}
  117. />
  118. )}
  119. {hasAssembly && (
  120. <Assembly {...parseAssembly(frame.package)} filePath={frame.absPath} />
  121. )}
  122. </Wrapper>
  123. );
  124. };
  125. export default withOrganization(Context);
  126. const StyledClippedBox = styled(ClippedBox)`
  127. padding: 0;
  128. `;
  129. const StyledIconFlag = styled(IconFlag)`
  130. margin-right: ${space(1)};
  131. `;
  132. const StyledContextLine = styled(ContextLine)`
  133. background: inherit;
  134. padding: 0;
  135. text-indent: 20px;
  136. z-index: 1000;
  137. `;
  138. const Wrapper = styled('ol')`
  139. && {
  140. border-radius: 0;
  141. }
  142. `;