@@ -673,3 +673,150 @@ describe('ConsoleFormatter', () => {
673673 } ) ;
674674 } ) ;
675675} ) ;
676+
677+ describe ( 'ConsoleFormatter - Source Map & Heavy Error Tests' , ( ) => {
678+
679+ it ( 'includes top frame location in JSON detailed output' , async ( ) => {
680+ const mockFrame = {
681+ name : 'myFunction' ,
682+ uiSourceCode : {
683+ uiLocation : ( line : number , column : number ) => ( {
684+ uiSourceCode : { url : ( ) => 'http://example.com/app.js' } ,
685+ lineNumber : line ,
686+ columnNumber : column ,
687+ linkText : ( ) => 'app.js:10:5' ,
688+ } ) ,
689+ } ,
690+ line : 9 ,
691+ column : 4 ,
692+ } ;
693+
694+ const mockStackTrace = {
695+ syncFragment : { frames : [ mockFrame ] } ,
696+ asyncFragments : [ ] ,
697+ } as unknown as DevTools . StackTrace . StackTrace . StackTrace ;
698+
699+ const mockError = {
700+ message : 'Something went wrong' ,
701+ stackTrace : mockStackTrace ,
702+ cause : undefined ,
703+ } as unknown as SymbolizedError ;
704+
705+ const uncaughtError = new UncaughtError ( { } as Protocol . Runtime . ExceptionDetails , 'target-1' ) ;
706+
707+ const formatter = await ConsoleFormatter . from ( uncaughtError , {
708+ id : 42 ,
709+ resolvedStackTraceForTesting : mockStackTrace ,
710+ resolvedCauseForTesting : mockError ,
711+ } ) ;
712+
713+ const json = formatter . toJSONDetailed ( ) ;
714+ assert . deepStrictEqual ( ( json as any ) . location , {
715+ url : 'http://example.com/app.js' ,
716+ lineNumber : 10 ,
717+ columnNumber : 5 ,
718+ } ) ;
719+ } ) ;
720+
721+ it ( 'handles heavy/nested errors with cause chain' , async ( ) => {
722+ const innerFrame = { line : 5 , column : 1 , url : 'lib.js' , name : 'inner' } ;
723+ const outerFrame = { line : 10 , column : 2 , url : 'app.js' , name : 'outer' } ;
724+
725+ const innerError = SymbolizedError . createForTesting (
726+ 'Inner error' ,
727+ { syncFragment : { frames : [ innerFrame ] } , asyncFragments : [ ] } as any ,
728+ ) ;
729+
730+ const outerError = SymbolizedError . createForTesting (
731+ 'Outer error' ,
732+ { syncFragment : { frames : [ outerFrame ] } , asyncFragments : [ ] } as any ,
733+ innerError ,
734+ ) ;
735+
736+ const uncaughtError = new UncaughtError ( { } as Protocol . Runtime . ExceptionDetails , 'heavy-1' ) ;
737+
738+ const formatter = await ConsoleFormatter . from ( uncaughtError , {
739+ id : 99 ,
740+ resolvedCauseForTesting : outerError ,
741+ resolvedStackTraceForTesting : outerError . stackTrace as any ,
742+ } ) ;
743+
744+ const detailed = formatter . toStringDetailed ( ) ;
745+ assert . ok ( detailed . includes ( 'Outer error' ) ) ;
746+ assert . ok ( detailed . includes ( 'Caused by: Inner error' ) ) ;
747+ assert . ok ( detailed . includes ( 'inner' ) ) ;
748+ assert . ok ( detailed . includes ( 'outer' ) ) ;
749+ } ) ;
750+
751+ it ( 'handles async fragments correctly' , async ( ) => {
752+ const syncFrame = { name : 'syncFunc' , line : 1 , column : 1 , url : 'sync.js' } ;
753+ const asyncFrame = { name : 'asyncFunc' , line : 5 , column : 2 , url : 'async.js' } ;
754+
755+ const stackTrace = {
756+ syncFragment : { frames : [ syncFrame ] } ,
757+ asyncFragments : [ { description : 'asyncTask' , frames : [ asyncFrame ] } ] ,
758+ } as unknown as DevTools . StackTrace . StackTrace . StackTrace ;
759+
760+ const error = SymbolizedError . createForTesting (
761+ 'Async error' ,
762+ stackTrace ,
763+ ) ;
764+
765+ const uncaughtError = new UncaughtError ( { } as Protocol . Runtime . ExceptionDetails , 'async-1' ) ;
766+
767+ const formatter = await ConsoleFormatter . from ( uncaughtError , {
768+ id : 100 ,
769+ resolvedCauseForTesting : error ,
770+ resolvedStackTraceForTesting : stackTrace ,
771+ } ) ;
772+
773+ const detailed = formatter . toStringDetailed ( ) ;
774+ assert . ok ( detailed . includes ( '--- asyncTask' ) ) ;
775+ assert . ok ( detailed . includes ( 'asyncFunc' ) ) ;
776+ } ) ;
777+
778+ it ( 'includes correct top frame location even when all others ignored' , async ( ) => {
779+ const ignoredFrame = { name : 'ignored' , line : 1 , column : 1 , url : 'ignore.js' } ;
780+ const topFrame = {
781+ name : 'topFrame' ,
782+ line : 10 ,
783+ column : 2 ,
784+ uiSourceCode : {
785+ uiLocation : ( line : number , column : number ) => ( {
786+ uiSourceCode : { url : ( ) => 'top.js' } ,
787+ lineNumber : line ,
788+ columnNumber : column ,
789+ linkText : ( ) => 'top.js:11:3' ,
790+ } ) ,
791+ } ,
792+ } ;
793+
794+ const stackTrace = {
795+ syncFragment : { frames : [ ignoredFrame as any , topFrame as any ] } ,
796+ asyncFragments : [ ] ,
797+ } as unknown as DevTools . StackTrace . StackTrace . StackTrace ;
798+
799+ const error = SymbolizedError . createForTesting (
800+ 'Test error' ,
801+ stackTrace ,
802+ ) ;
803+
804+ const uncaughtError = new UncaughtError ( { } as Protocol . Runtime . ExceptionDetails , 'ignore-test' ) ;
805+
806+ const formatter = await ConsoleFormatter . from ( uncaughtError , {
807+ id : 101 ,
808+ resolvedStackTraceForTesting : stackTrace ,
809+ resolvedCauseForTesting : error ,
810+ isIgnoredForTesting : frame => frame . url === 'ignore.js' ,
811+ } ) ;
812+
813+ const json = formatter . toJSONDetailed ( ) ;
814+ assert . deepStrictEqual ( ( json as any ) . location , {
815+ url : 'top.js' ,
816+ lineNumber : 11 ,
817+ columnNumber : 3 ,
818+ } ) ;
819+ } ) ;
820+
821+ } ) ;
822+
0 commit comments