@@ -61,6 +61,9 @@ use zip::{write::FileOptions, ZipWriter};
6161use symbolic_common:: { Arch , AsSelf , CodeId , DebugId } ;
6262
6363use crate :: base:: * ;
64+ use crate :: js:: {
65+ discover_debug_id, discover_sourcemap_embedded_debug_id, discover_sourcemaps_location,
66+ } ;
6467use crate :: { DebugSession , ObjectKind , ObjectLike } ;
6568
6669/// Magic bytes of a source bundle. They are prepended to the ZIP file.
@@ -400,38 +403,37 @@ impl<'a> SourceFileDescriptor<'a> {
400403 /// The debug ID of the file if available.
401404 ///
402405 /// For source maps or minified source files symbolic supports embedded debug IDs. If they
403- /// are in use, the debug ID is returned from here.
406+ /// are in use, the debug ID is returned from here. The debug ID is discovered from the
407+ /// file's `debug-id` header or the embedded `debugId` reference in the file body.
404408 pub fn debug_id ( & self ) -> Option < DebugId > {
405- self . file_info . and_then ( |x| x. debug_id ( ) )
409+ self . file_info . and_then ( |x| x. debug_id ( ) ) . or_else ( || {
410+ if matches ! ( self . ty( ) , SourceFileType :: MinifiedSource ) {
411+ self . contents ( ) . and_then ( discover_debug_id)
412+ } else if matches ! ( self . ty( ) , SourceFileType :: SourceMap ) {
413+ self . contents ( )
414+ . and_then ( discover_sourcemap_embedded_debug_id)
415+ } else {
416+ None
417+ }
418+ } )
406419 }
407420
408421 /// The source mapping URL reference of the file.
409422 ///
410423 /// This is used to refer to a source map from a minified file. Only minified source files
411- /// will have a relationship to a source map.
424+ /// will have a relationship to a source map. The source mapping is discovered either from
425+ /// a `sourcemap` header in the source manifest, or the `sourceMappingURL` reference in the body.
412426 pub fn source_mapping_url ( & self ) -> Option < & str > {
413- if let Some ( file_info) = self . file_info {
414- if let Some ( url) = file_info. source_mapping_url ( ) {
415- return Some ( url) ;
416- }
417- }
418- if let Some ( ref contents) = self . contents {
419- if let Some ( url) = discover_sourcemaps_location ( contents) {
420- return Some ( url) ;
421- }
422- }
423- None
424- }
425- }
426-
427- /// Parses a sourceMappingURL comment in a file to discover a sourcemap reference.
428- fn discover_sourcemaps_location ( contents : & str ) -> Option < & str > {
429- for line in contents. lines ( ) . rev ( ) {
430- if line. starts_with ( "//# sourceMappingURL=" ) || line. starts_with ( "//@ sourceMappingURL=" ) {
431- return Some ( line[ 21 ..] . trim ( ) ) ;
432- }
427+ self . file_info
428+ . and_then ( |x| x. source_mapping_url ( ) )
429+ . or_else ( || {
430+ if matches ! ( self . ty( ) , SourceFileType :: MinifiedSource ) {
431+ self . contents ( ) . and_then ( discover_sourcemaps_location)
432+ } else {
433+ None
434+ }
435+ } )
433436 }
434- None
435437}
436438
437439/// Version number of a [`SourceBundle`](struct.SourceBundle.html).
@@ -1416,7 +1418,7 @@ mod tests {
14161418 info. set_ty ( SourceFileType :: MinifiedSource ) ;
14171419 bundle. add_file (
14181420 "bar.js" ,
1419- & b"filecontents\n //@ sourceMappingURL=bar.js.map" [ ..] ,
1421+ & b"filecontents\n //# sourceMappingURL=bar.js.map" [ ..] ,
14201422 info,
14211423 ) ?;
14221424
@@ -1436,6 +1438,70 @@ mod tests {
14361438 Ok ( ( ) )
14371439 }
14381440
1441+ #[ test]
1442+ fn test_source_embedded_debug_id ( ) -> Result < ( ) , SourceBundleError > {
1443+ let mut writer = Cursor :: new ( Vec :: new ( ) ) ;
1444+ let mut bundle = SourceBundleWriter :: start ( & mut writer) ?;
1445+
1446+ let mut info = SourceFileInfo :: default ( ) ;
1447+ info. set_url ( "https://example.com/bar.min.js" . into ( ) ) ;
1448+ info. set_ty ( SourceFileType :: MinifiedSource ) ;
1449+ bundle. add_file (
1450+ "bar.js" ,
1451+ & b"filecontents\n //# debugId=5b65abfb23384f0bb3b964c8f734d43f" [ ..] ,
1452+ info,
1453+ ) ?;
1454+
1455+ bundle. finish ( ) ?;
1456+ let bundle_bytes = writer. into_inner ( ) ;
1457+ let bundle = SourceBundle :: parse ( & bundle_bytes) ?;
1458+
1459+ let sess = bundle. debug_session ( ) . unwrap ( ) ;
1460+ let f = sess
1461+ . source_by_url ( "https://example.com/bar.min.js" )
1462+ . unwrap ( )
1463+ . expect ( "should exist" ) ;
1464+ assert_eq ! ( f. ty( ) , SourceFileType :: MinifiedSource ) ;
1465+ assert_eq ! (
1466+ f. debug_id( ) ,
1467+ Some ( "5b65abfb-2338-4f0b-b3b9-64c8f734d43f" . parse( ) . unwrap( ) )
1468+ ) ;
1469+
1470+ Ok ( ( ) )
1471+ }
1472+
1473+ #[ test]
1474+ fn test_sourcemap_embedded_debug_id ( ) -> Result < ( ) , SourceBundleError > {
1475+ let mut writer = Cursor :: new ( Vec :: new ( ) ) ;
1476+ let mut bundle = SourceBundleWriter :: start ( & mut writer) ?;
1477+
1478+ let mut info = SourceFileInfo :: default ( ) ;
1479+ info. set_url ( "https://example.com/bar.js.map" . into ( ) ) ;
1480+ info. set_ty ( SourceFileType :: SourceMap ) ;
1481+ bundle. add_file (
1482+ "bar.js.map" ,
1483+ & br#"{"debug_id": "5b65abfb-2338-4f0b-b3b9-64c8f734d43f"}"# [ ..] ,
1484+ info,
1485+ ) ?;
1486+
1487+ bundle. finish ( ) ?;
1488+ let bundle_bytes = writer. into_inner ( ) ;
1489+ let bundle = SourceBundle :: parse ( & bundle_bytes) ?;
1490+
1491+ let sess = bundle. debug_session ( ) . unwrap ( ) ;
1492+ let f = sess
1493+ . source_by_url ( "https://example.com/bar.js.map" )
1494+ . unwrap ( )
1495+ . expect ( "should exist" ) ;
1496+ assert_eq ! ( f. ty( ) , SourceFileType :: SourceMap ) ;
1497+ assert_eq ! (
1498+ f. debug_id( ) ,
1499+ Some ( "5b65abfb-2338-4f0b-b3b9-64c8f734d43f" . parse( ) . unwrap( ) )
1500+ ) ;
1501+
1502+ Ok ( ( ) )
1503+ }
1504+
14391505 #[ test]
14401506 fn test_il2cpp_reference ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
14411507 let mut cpp_file = NamedTempFile :: new ( ) ?;
0 commit comments