- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 1.7k
ref(browser): Split stack line parsers into individual functions and simplify further #4555
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
          
     Merged
      
      
    
  
     Merged
                    Changes from all commits
      Commits
    
    
            Show all changes
          
          
            20 commits
          
        
        Select commit
          Hold shift + click to select a range
      
      0ec6249
              
                Refactor tests and minor improvements
              
              
                timfish 5563471
              
                Remove TraceKitStackFrame
              
              
                timfish 4db0290
              
                Remove undefined
              
              
                timfish 8e09b5e
              
                Merge remote-tracking branch 'upstream/master' into remove-tracekitst…
              
              
                timfish 87c5628
              
                Merge opera parser to slim down code
              
              
                timfish 245eee9
              
                Lil tidy
              
              
                timfish 8723236
              
                split into functions
              
              
                timfish ee31a1a
              
                More simplify
              
              
                timfish 6627be7
              
                Minimise fields
              
              
                timfish e45decc
              
                Merge remote-tracking branch 'upstream/master' into sep-parsers
              
              
                timfish 328118b
              
                Re order so we dont break opera!
              
              
                timfish 3c1e7c2
              
                Move the regex
              
              
                timfish 98be3a1
              
                Move frame reverse into parser and reverse all test frames 😭
              
              
                timfish 11a4318
              
                simplify pop
              
              
                timfish 1c40c42
              
                Couple more simplifications
              
              
                timfish 24cc5a4
              
                Merge remote-tracking branch 'upstream/master' into sep-parsers
              
              
                timfish 2bee1b4
              
                Remove useless else
              
              
                timfish 24a18f3
              
                Move `in_app` to initial declaration
              
              
                timfish 426828e
              
                Fix bad code
              
              
                timfish cb8af0d
              
                Merge remote-tracking branch 'upstream/master' into sep-parsers
              
              
                timfish File filter
Filter by extension
Conversations
          Failed to load comments.   
        
        
          
      Loading
        
  Jump to
        
          Jump to file
        
      
      
          Failed to load files.   
        
        
          
      Loading
        
  Diff view
Diff view
There are no files selected for viewing
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,148 @@ | ||
| import { StackFrame } from '@sentry/types'; | ||
| import { StackLineParser } from '@sentry/utils'; | ||
|  | ||
| // global reference to slice | ||
| const UNKNOWN_FUNCTION = '?'; | ||
|  | ||
| function createFrame(filename: string, func: string, lineno?: number, colno?: number): StackFrame { | ||
| const frame: StackFrame = { | ||
| filename, | ||
| function: func, | ||
| // All browser frames are considered in_app | ||
| in_app: true, | ||
| }; | ||
|  | ||
| if (lineno !== undefined) { | ||
| frame.lineno = lineno; | ||
| } | ||
|  | ||
| if (colno !== undefined) { | ||
| frame.colno = colno; | ||
| } | ||
|  | ||
| return frame; | ||
| } | ||
|  | ||
| // Chromium based browsers: Chrome, Brave, new Opera, new Edge | ||
| const chromeRegex = | ||
| /^\s*at (?:(.*?) ?\((?:address at )?)?((?:file|https?|blob|chrome-extension|address|native|eval|webpack|<anonymous>|[-a-z]+:|.*bundle|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i; | ||
| const chromeEvalRegex = /\((\S*)(?::(\d+))(?::(\d+))\)/; | ||
|  | ||
| export const chrome: StackLineParser = line => { | ||
| const parts = chromeRegex.exec(line); | ||
|  | ||
| if (parts) { | ||
| const isEval = parts[2] && parts[2].indexOf('eval') === 0; // start of line | ||
|  | ||
| if (isEval) { | ||
| const subMatch = chromeEvalRegex.exec(parts[2]); | ||
|  | ||
| if (subMatch) { | ||
| // throw out eval line/column and use top-most line/column number | ||
| parts[2] = subMatch[1]; // url | ||
| parts[3] = subMatch[2]; // line | ||
| parts[4] = subMatch[3]; // column | ||
| } | ||
| } | ||
|  | ||
| // Kamil: One more hack won't hurt us right? Understanding and adding more rules on top of these regexps right now | ||
| // would be way too time consuming. (TODO: Rewrite whole RegExp to be more readable) | ||
| const [func, filename] = extractSafariExtensionDetails(parts[1] || UNKNOWN_FUNCTION, parts[2]); | ||
|  | ||
| return createFrame(filename, func, parts[3] ? +parts[3] : undefined, parts[4] ? +parts[4] : undefined); | ||
| } | ||
|  | ||
| return; | ||
| }; | ||
|  | ||
| // gecko regex: `(?:bundle|\d+\.js)`: `bundle` is for react native, `\d+\.js` also but specifically for ram bundles because it | ||
| // generates filenames without a prefix like `file://` the filenames in the stacktrace are just 42.js | ||
| // We need this specific case for now because we want no other regex to match. | ||
| const geckoREgex = | ||
| /^\s*(.*?)(?:\((.*?)\))?(?:^|@)?((?:file|https?|blob|chrome|webpack|resource|moz-extension|capacitor).*?:\/.*?|\[native code\]|[^@]*(?:bundle|\d+\.js)|\/[\w\-. /=]+)(?::(\d+))?(?::(\d+))?\s*$/i; | ||
| const geckoEvalRegex = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i; | ||
|  | ||
| export const gecko: StackLineParser = line => { | ||
| const parts = geckoREgex.exec(line); | ||
|  | ||
| if (parts) { | ||
| const isEval = parts[3] && parts[3].indexOf(' > eval') > -1; | ||
| if (isEval) { | ||
| const subMatch = geckoEvalRegex.exec(parts[3]); | ||
|  | ||
| if (subMatch) { | ||
| // throw out eval line/column and use top-most line number | ||
| parts[1] = parts[1] || `eval`; | ||
| parts[3] = subMatch[1]; | ||
| parts[4] = subMatch[2]; | ||
| parts[5] = ''; // no column when eval | ||
| } | ||
| } | ||
|  | ||
| let filename = parts[3]; | ||
| let func = parts[1] || UNKNOWN_FUNCTION; | ||
| [func, filename] = extractSafariExtensionDetails(func, filename); | ||
|  | ||
| return createFrame(filename, func, parts[4] ? +parts[4] : undefined, parts[5] ? +parts[5] : undefined); | ||
| } | ||
|  | ||
| return; | ||
| }; | ||
|  | ||
| const winjsRegex = | ||
| /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i; | ||
|  | ||
| export const winjs: StackLineParser = line => { | ||
| const parts = winjsRegex.exec(line); | ||
|  | ||
| return parts | ||
| ? createFrame(parts[2], parts[1] || UNKNOWN_FUNCTION, +parts[3], parts[4] ? +parts[4] : undefined) | ||
| : undefined; | ||
| }; | ||
|  | ||
| const opera10Regex = / line (\d+).*script (?:in )?(\S+)(?:: in function (\S+))?$/i; | ||
|  | ||
| export const opera10: StackLineParser = line => { | ||
| const parts = opera10Regex.exec(line); | ||
| return parts ? createFrame(parts[2], parts[3] || UNKNOWN_FUNCTION, +parts[1]) : undefined; | ||
| }; | ||
|  | ||
| const opera11Regex = | ||
| / line (\d+), column (\d+)\s*(?:in (?:<anonymous function: ([^>]+)>|([^)]+))\(.*\))? in (.*):\s*$/i; | ||
|  | ||
| export const opera11: StackLineParser = line => { | ||
| const parts = opera11Regex.exec(line); | ||
| return parts ? createFrame(parts[5], parts[3] || parts[4] || UNKNOWN_FUNCTION, +parts[1], +parts[2]) : undefined; | ||
| }; | ||
|  | ||
| /** | ||
| * Safari web extensions, starting version unknown, can produce "frames-only" stacktraces. | ||
| * What it means, is that instead of format like: | ||
| * | ||
| * Error: wat | ||
| * at function@url:row:col | ||
| * at function@url:row:col | ||
| * at function@url:row:col | ||
| * | ||
| * it produces something like: | ||
| * | ||
| * function@url:row:col | ||
| * function@url:row:col | ||
| * function@url:row:col | ||
| * | ||
| * Because of that, it won't be captured by `chrome` RegExp and will fall into `Gecko` branch. | ||
| * This function is extracted so that we can use it in both places without duplicating the logic. | ||
| * Unfortunately "just" changing RegExp is too complicated now and making it pass all tests | ||
| * and fix this case seems like an impossible, or at least way too time-consuming task. | ||
| */ | ||
| const extractSafariExtensionDetails = (func: string, filename: string): [string, string] => { | ||
| const isSafariExtension = func.indexOf('safari-extension') !== -1; | ||
| const isSafariWebExtension = func.indexOf('safari-web-extension') !== -1; | ||
|  | ||
| return isSafariExtension || isSafariWebExtension | ||
| ? [ | ||
| func.indexOf('@') !== -1 ? func.split('@')[0] : UNKNOWN_FUNCTION, | ||
| isSafariExtension ? `safari-extension:${filename}` : `safari-web-extension:${filename}`, | ||
| ] | ||
| : [func, filename]; | ||
| }; | 
      
      Oops, something went wrong.
        
    
  
  Add this suggestion to a batch that can be applied as a single commit.
  This suggestion is invalid because no changes were made to the code.
  Suggestions cannot be applied while the pull request is closed.
  Suggestions cannot be applied while viewing a subset of changes.
  Only one suggestion per line can be applied in a batch.
  Add this suggestion to a batch that can be applied as a single commit.
  Applying suggestions on deleted lines is not supported.
  You must change the existing code in this line in order to create a valid suggestion.
  Outdated suggestions cannot be applied.
  This suggestion has been applied or marked resolved.
  Suggestions cannot be applied from pending reviews.
  Suggestions cannot be applied on multi-line comments.
  Suggestions cannot be applied while the pull request is queued to merge.
  Suggestion cannot be applied right now. Please check back later.
  
    
  
    
Uh oh!
There was an error while loading. Please reload this page.