import path from 'path' ; import { SourceMapConsumer , RawSourceMap } from 'source-map' ; import { DurationEvent } from '../types/EventInterfaces' ; import { SourceMap } from '../types/SourceMap' ; param defaultCategory param url const findNodeModuleNameIfExists = ( defaultCategory , url ) : string => { const obtainCategory = ( url ) : string => { const dirs = url . substring ( url . lastIndexOf ( `${ path . sep }node_modules${ path . sep }` ) ) . split ( path . sep ) ; return dirs . length > 2 && dirs [ 1 ] === 'node_modules' ? dirs [ 2 ] : defaultCategory ; } ; return url ? obtainCategory ( url ) : defaultCategory ; } ; param nodeModuleName see findNodeModuleNameIfExists const improveCategories = ( nodeModuleName , defaultCategory ) : string => { if ( nodeModuleName === defaultCategory ) { return defaultCategory ; } const reactNativeModuleNames = [ 'react-native' , 'react' , 'metro' ] ; if ( reactNativeModuleNames . includes ( nodeModuleName ) ) { return 'react-native-internals' ; } else { return 'other_node_modules' ; } } ; param { SourceMap } sourceMap param { DurationEvent [ ] } chromeEvents param { string } indexBundleFileName throws returns { DurationEvent [ ] } const applySourceMapsToEvents = async ( sourceMap , chromeEvents , indexBundleFileName ) : Promise < DurationEvent [ ] > => { const rawSourceMap = { version : Number ( sourceMap . version ) , file : indexBundleFileName || 'index.bundle' , sources : sourceMap . sources , mappings : sourceMap . mappings , names : sourceMap . names } ; const consumer = await new SourceMapConsumer ( rawSourceMap ) ; const events = chromeEvents . map ( ( event ) => { if ( event . args ) { const sm = consumer . originalPositionFor ( { line : Number ( event . args . line ) , column : Number ( event . args . column ) } ) ; /**
             * The categories can help us better visualise the profile if we modify the categories.
             * We change these categories only in the root level and not deeper inside the args, just so we have our
             * original categories as well as these modified categories (as the modified categories simply help with visualisation)
             */ const nodeModuleNameIfAvailable = findNodeModuleNameIfExists ( event . cat ! , sm . source ) ; event . cat = improveCategories ( nodeModuleNameIfAvailable , event . cat ! ) ; event . args = { ... event . args , url : sm . source , line : sm . line , column : sm . column , params : sm . name , allocatedCategory : event . cat , allocatedName : event . name , node_module : nodeModuleNameIfAvailable } ; } else { throw new Error ( `Source maps could not be derived for an event at ${ event . ts } and with stackFrame ID ${ event . sf }` ) ; } return event ; } ) ; consumer . destroy ( ) ; return events ; } ; export default applySourceMapsToEvents ;