@@ -15,7 +15,7 @@ use crate::{
1515 object_pool:: ObjectPool ,
1616 source:: { Mapping , OriginalLocation } ,
1717 source_content_lines:: SourceContentLines ,
18- with_indices :: WithIndices ,
18+ with_utf16 :: WithUtf16 ,
1919 MapOptions , Rope , SourceMap ,
2020} ;
2121
@@ -259,7 +259,7 @@ where
259259 last_line = line;
260260 }
261261
262- ( line_count. max ( 1 ) , last_line. len ( ) )
262+ ( line_count. max ( 1 ) , last_line. utf16_len ( ) )
263263 } ;
264264 GeneratedInfo {
265265 generated_line : generated_line as u32 ,
@@ -443,7 +443,7 @@ where
443443{
444444 let lines = split_into_lines ( & source) ;
445445 let line_with_indices_list = lines
446- . map ( |line| WithIndices :: new ( object_pool, line) )
446+ . map ( |line| WithUtf16 :: new ( object_pool, line) )
447447 . collect :: < Vec < _ > > ( ) ;
448448
449449 if line_with_indices_list. is_empty ( ) {
@@ -470,8 +470,11 @@ where
470470 } else {
471471 line_with_indices_list. len ( )
472472 } as u32 ;
473- let final_column: u32 =
474- if last_new_line { 0 } else { last_line. len ( ) } as u32 ;
473+ let final_column: u32 = if last_new_line {
474+ 0
475+ } else {
476+ last_line. utf16_len ( )
477+ } as u32 ;
475478 let mut current_generated_line: u32 = 1 ;
476479 let mut current_generated_column: u32 = 0 ;
477480 let mut mapping_active = false ;
@@ -713,7 +716,11 @@ where
713716 } else {
714717 lines. len ( )
715718 } as u32 ;
716- let final_column = if last_new_line { 0 } else { last_line. len ( ) } as u32 ;
719+ let final_column = if last_new_line {
720+ 0
721+ } else {
722+ last_line. utf16_len ( )
723+ } as u32 ;
717724 GeneratedInfo {
718725 generated_line : final_line,
719726 generated_column : final_column,
@@ -1300,6 +1307,9 @@ pub trait SourceText<'a>: Default + Clone + ToString {
13001307 /// Returns the length of the text in bytes.
13011308 fn len ( & self ) -> usize ;
13021309
1310+ /// Returns the utf16 length of the text in bytes.
1311+ fn utf16_len ( & self ) -> usize ;
1312+
13031313 /// Converts this text into a Rope.
13041314 fn into_rope ( self ) -> Rope < ' a >
13051315 where
@@ -1349,6 +1359,10 @@ impl<'a> SourceText<'a> for Rope<'a> {
13491359 fn get_byte ( & self , byte_index : usize ) -> Option < u8 > {
13501360 self . get_byte ( byte_index)
13511361 }
1362+
1363+ fn utf16_len ( & self ) -> usize {
1364+ self . utf16_len ( )
1365+ }
13521366}
13531367
13541368impl < ' a > SourceText < ' a > for & ' a str {
@@ -1391,4 +1405,142 @@ impl<'a> SourceText<'a> for &'a str {
13911405 fn get_byte ( & self , byte_index : usize ) -> Option < u8 > {
13921406 self . as_bytes ( ) . get ( byte_index) . copied ( )
13931407 }
1408+
1409+ fn utf16_len ( & self ) -> usize {
1410+ self . encode_utf16 ( ) . count ( )
1411+ }
1412+ }
1413+
1414+ #[ cfg( test) ]
1415+ mod tests {
1416+ use std:: sync:: LazyLock ;
1417+
1418+ use super :: {
1419+ stream_chunks_of_source_map_final, stream_chunks_of_source_map_full,
1420+ stream_chunks_of_source_map_lines_final,
1421+ stream_chunks_of_source_map_lines_full, GeneratedInfo ,
1422+ } ;
1423+ use crate :: { Mapping , ObjectPool , OriginalLocation , SourceMap } ;
1424+
1425+ const UTF16_SOURCE : & ' static str = "var i18n = JSON.parse('{\" 魑魅魍魉\" :{\" en-US\" :\" Evil spirits\" ,\" zh-CN\" :\" 魑魅魍魉\" }}');\n var __webpack_exports___ = i18n[\" 魑魅魍魉\" ];\n export { __webpack_exports___ as 魑魅魍魉 };" ;
1426+
1427+ const UTF16_SOURCE_MAP : LazyLock < SourceMap > = LazyLock :: new ( || {
1428+ SourceMap :: from_json ( "{\" version\" :3,\" sources\" :[\" i18.js\" ],\" sourcesContent\" :[\" var i18n = JSON.parse('{\\ \" 魑魅魍魉\\ \" :{\\ \" en-US\\ \" :\\ \" Evil spirits\\ \" ,\\ \" zh-CN\\ \" :\\ \" 魑魅魍魉\\ \" }}');\\ nvar __webpack_exports___ = i18n[\\ \" 魑魅魍魉\\ \" ];\\ nexport { __webpack_exports___ as 魑魅魍魉 };\\ n\" ],\" names\" :[\" i18n\" ,\" JSON\" ,\" __webpack_exports___\" ,\" 魑魅魍魉\" ],\" mappings\" :\" AAAA,IAAIA,OAAOC,KAAK,KAAK,CAAC;AACtB,IAAIC,uBAAuBF,IAAI,CAAC,OAAO;AACvC,SAASE,wBAAwBC,IAAI,GAAG\" }" ) . unwrap ( )
1429+ } ) ;
1430+
1431+ #[ test]
1432+ fn test_stream_chunks_of_source_map_full_handles_multi_unit_utf16 ( ) {
1433+ let source = UTF16_SOURCE ;
1434+ let source_map = & * UTF16_SOURCE_MAP ;
1435+ let object_pool = ObjectPool :: default ( ) ;
1436+
1437+ let mut chunks = vec ! [ ] ;
1438+
1439+ let generated_info = stream_chunks_of_source_map_full (
1440+ & object_pool,
1441+ source,
1442+ source_map,
1443+ & mut |chunk, mapping| {
1444+ chunks. push ( ( chunk. unwrap ( ) , mapping) ) ;
1445+ } ,
1446+ & mut |_i, _source, _source_content| { } ,
1447+ & mut |_i, _name| { } ,
1448+ ) ;
1449+
1450+ assert_eq ! (
1451+ chunks,
1452+ vec![
1453+ ( "var " . into( ) , Mapping { generated_line: 1 , generated_column: 0 , original: Some ( OriginalLocation { source_index: 0 , original_line: 1 , original_column: 0 , name_index: None } ) } ) ,
1454+ ( "i18n = " . into( ) , Mapping { generated_line: 1 , generated_column: 4 , original: Some ( OriginalLocation { source_index: 0 , original_line: 1 , original_column: 4 , name_index: Some ( 0 ) } ) } ) ,
1455+ ( "JSON." . into( ) , Mapping { generated_line: 1 , generated_column: 11 , original: Some ( OriginalLocation { source_index: 0 , original_line: 1 , original_column: 11 , name_index: Some ( 1 ) } ) } ) ,
1456+ ( "parse" . into( ) , Mapping { generated_line: 1 , generated_column: 16 , original: Some ( OriginalLocation { source_index: 0 , original_line: 1 , original_column: 16 , name_index: None } ) } ) ,
1457+ ( "(" . into( ) , Mapping { generated_line: 1 , generated_column: 21 , original: Some ( OriginalLocation { source_index: 0 , original_line: 1 , original_column: 21 , name_index: None } ) } ) ,
1458+ ( "'{\" 魑魅魍魉\" :{\" en-US\" :\" Evil spirits\" ,\" zh-CN\" :\" 魑魅魍魉\" }}');\n " . into( ) , Mapping { generated_line: 1 , generated_column: 22 , original: Some ( OriginalLocation { source_index: 0 , original_line: 1 , original_column: 22 , name_index: None } ) } ) ,
1459+ ( "var " . into( ) , Mapping { generated_line: 2 , generated_column: 0 , original: Some ( OriginalLocation { source_index: 0 , original_line: 2 , original_column: 0 , name_index: None } ) } ) ,
1460+ ( "__webpack_exports___ = " . into( ) , Mapping { generated_line: 2 , generated_column: 4 , original: Some ( OriginalLocation { source_index: 0 , original_line: 2 , original_column: 4 , name_index: Some ( 2 ) } ) } ) ,
1461+ ( "i18n" . into( ) , Mapping { generated_line: 2 , generated_column: 27 , original: Some ( OriginalLocation { source_index: 0 , original_line: 2 , original_column: 27 , name_index: Some ( 0 ) } ) } ) ,
1462+ ( "[" . into( ) , Mapping { generated_line: 2 , generated_column: 31 , original: Some ( OriginalLocation { source_index: 0 , original_line: 2 , original_column: 31 , name_index: None } ) } ) ,
1463+ ( "\" 魑魅魍魉\" ]" . into( ) , Mapping { generated_line: 2 , generated_column: 32 , original: Some ( OriginalLocation { source_index: 0 , original_line: 2 , original_column: 32 , name_index: None } ) } ) ,
1464+ ( ";\n " . into( ) , Mapping { generated_line: 2 , generated_column: 39 , original: Some ( OriginalLocation { source_index: 0 , original_line: 2 , original_column: 39 , name_index: None } ) } ) ,
1465+ ( "export { " . into( ) , Mapping { generated_line: 3 , generated_column: 0 , original: Some ( OriginalLocation { source_index: 0 , original_line: 3 , original_column: 0 , name_index: None } ) } ) ,
1466+ ( "__webpack_exports___ as " . into( ) , Mapping { generated_line: 3 , generated_column: 9 , original: Some ( OriginalLocation { source_index: 0 , original_line: 3 , original_column: 9 , name_index: Some ( 2 ) } ) } ) ,
1467+ ( "魑魅魍魉" . into( ) , Mapping { generated_line: 3 , generated_column: 33 , original: Some ( OriginalLocation { source_index: 0 , original_line: 3 , original_column: 33 , name_index: Some ( 3 ) } ) } ) ,
1468+ ( " };" . into( ) , Mapping { generated_line: 3 , generated_column: 37 , original: Some ( OriginalLocation { source_index: 0 , original_line: 3 , original_column: 37 , name_index: None } ) } )
1469+ ]
1470+ ) ;
1471+
1472+ assert_eq ! (
1473+ generated_info,
1474+ GeneratedInfo {
1475+ generated_line: 3 ,
1476+ generated_column: 40
1477+ }
1478+ )
1479+ }
1480+
1481+ #[ test]
1482+ fn test_stream_chunks_of_source_map_final_handles_multi_unit_utf16 ( ) {
1483+ let source = UTF16_SOURCE ;
1484+ let source_map = & * UTF16_SOURCE_MAP ;
1485+
1486+ let generated_info = stream_chunks_of_source_map_final (
1487+ source,
1488+ source_map,
1489+ & mut |_chunk, _mapping| { } ,
1490+ & mut |_i, _source, _source_content| { } ,
1491+ & mut |_i, _name| { } ,
1492+ ) ;
1493+
1494+ assert_eq ! (
1495+ generated_info,
1496+ GeneratedInfo {
1497+ generated_line: 3 ,
1498+ generated_column: 40
1499+ }
1500+ )
1501+ }
1502+
1503+ #[ test]
1504+ fn test_stream_chunks_of_source_map_lines_final_handles_multi_unit_utf16 ( ) {
1505+ let source = UTF16_SOURCE ;
1506+ let source_map = & * UTF16_SOURCE_MAP ;
1507+
1508+ let generated_info = stream_chunks_of_source_map_lines_final (
1509+ source,
1510+ source_map,
1511+ & mut |_chunk, _mapping| { } ,
1512+ & mut |_i, _source, _source_content| { } ,
1513+ & mut |_i, _name| { } ,
1514+ ) ;
1515+
1516+ assert_eq ! (
1517+ generated_info,
1518+ GeneratedInfo {
1519+ generated_line: 3 ,
1520+ generated_column: 40
1521+ }
1522+ )
1523+ }
1524+
1525+ #[ test]
1526+ fn test_stream_chunks_of_source_map_lines_full_handles_multi_unit_utf16 ( ) {
1527+ let source = UTF16_SOURCE ;
1528+ let source_map = & * UTF16_SOURCE_MAP ;
1529+
1530+ let generated_info = stream_chunks_of_source_map_lines_full (
1531+ source,
1532+ source_map,
1533+ & mut |_chunk, _mapping| { } ,
1534+ & mut |_i, _source, _source_content| { } ,
1535+ & mut |_i, _name| { } ,
1536+ ) ;
1537+
1538+ assert_eq ! (
1539+ generated_info,
1540+ GeneratedInfo {
1541+ generated_line: 3 ,
1542+ generated_column: 40
1543+ }
1544+ )
1545+ }
13941546}
0 commit comments