fix(codegen): sourcemap token name should be original name (#2843)

close https://github.com/oxc-project/oxc/issues/2753.
This commit is contained in:
underfin 2024-03-28 20:14:10 +08:00 committed by GitHub
parent b199cb89a2
commit 6177c2f7ef
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 67 additions and 12 deletions

View file

@ -1015,7 +1015,7 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for IdentifierReference<'a> {
// }
// }
// }
p.add_source_mapping_for_name(self.span.start, &self.name);
p.add_source_mapping_for_name(self.span, &self.name);
p.print_str(self.name.as_bytes());
}
}
@ -1029,13 +1029,13 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for IdentifierName<'a> {
impl<'a, const MINIFY: bool> Gen<MINIFY> for BindingIdentifier<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) {
p.print_symbol(self.span.start, self.symbol_id.get(), &self.name);
p.print_symbol(self.span, self.symbol_id.get(), &self.name);
}
}
impl<'a, const MINIFY: bool> Gen<MINIFY> for LabelIdentifier<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) {
p.add_source_mapping_for_name(self.span.start, &self.name);
p.add_source_mapping_for_name(self.span, &self.name);
p.print_str(self.name.as_bytes());
}
}
@ -2057,7 +2057,7 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ClassElement<'a> {
impl<'a, const MINIFY: bool> Gen<MINIFY> for JSXIdentifier<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) {
p.add_source_mapping_for_name(self.span.start, &self.name);
p.add_source_mapping_for_name(self.span, &self.name);
p.print_str(self.name.as_bytes());
}
}
@ -2398,7 +2398,7 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for AccessorProperty<'a> {
impl<'a, const MINIFY: bool> Gen<MINIFY> for PrivateIdentifier<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) {
p.add_source_mapping_for_name(self.span.start, &self.name);
p.add_source_mapping_for_name(self.span, &self.name);
p.print(b'#');
p.print_str(self.name.as_bytes());
}

View file

@ -303,7 +303,7 @@ impl<const MINIFY: bool> Codegen<MINIFY> {
}
}
fn print_symbol(&mut self, start: u32, _symbol_id: Option<SymbolId>, fallback: &Atom) {
fn print_symbol(&mut self, span: Span, _symbol_id: Option<SymbolId>, fallback: &Atom) {
// if let Some(mangler) = &self.mangler {
// if let Some(symbol_id) = symbol_id {
// let name = mangler.get_symbol_name(symbol_id);
@ -311,7 +311,7 @@ impl<const MINIFY: bool> Codegen<MINIFY> {
// return;
// }
// }
self.add_source_mapping_for_name(start, fallback);
self.add_source_mapping_for_name(span, fallback);
self.print_str(fallback.as_bytes());
}
@ -412,8 +412,8 @@ impl<const MINIFY: bool> Codegen<MINIFY> {
self.sourcemap_builder.add_source_mapping(&self.code, position, None);
}
fn add_source_mapping_for_name(&mut self, position: u32, name: &str) {
self.sourcemap_builder.add_source_mapping(&self.code, position, Some(name));
fn add_source_mapping_for_name(&mut self, span: Span, name: &str) {
self.sourcemap_builder.add_source_mapping_for_name(&self.code, span, name);
}
}

View file

@ -1,3 +1,6 @@
use std::sync::Arc;
use oxc_span::Span;
use oxc_syntax::identifier::{LS, PS};
// Irregular line breaks - '\u{2028}' (LS) and '\u{2029}' (PS)
@ -18,11 +21,11 @@ pub struct LineOffsetTable {
byte_offset_to_start_of_line: usize,
}
#[derive(Default)]
#[allow(clippy::struct_field_names)]
pub struct SourcemapBuilder {
enable_sourcemap: bool,
source_id: u32,
original_source: Arc<str>,
last_generated_update: usize,
last_position: Option<u32>,
last_search_line: usize,
@ -32,25 +35,53 @@ pub struct SourcemapBuilder {
generated_column: u32,
}
impl Default for SourcemapBuilder {
fn default() -> Self {
Self {
enable_sourcemap: false,
source_id: 0,
original_source: "".into(),
last_generated_update: 0,
last_position: None,
last_search_line: 0,
line_offset_tables: vec![],
sourcemap_builder: oxc_sourcemap::SourceMapBuilder::default(),
generated_line: 0,
generated_column: 0,
}
}
}
impl SourcemapBuilder {
pub fn with_name_and_source(&mut self, name: &str, source: &str) {
self.enable_sourcemap = true;
self.line_offset_tables = Self::generate_line_offset_tables(source);
self.source_id = self.sourcemap_builder.set_source_and_content(name, source);
self.original_source = source.into();
}
pub fn into_sourcemap(self) -> Option<oxc_sourcemap::SourceMap> {
self.enable_sourcemap.then(|| self.sourcemap_builder.into_sourcemap())
}
pub fn add_source_mapping(&mut self, output: &[u8], position: u32, name: Option<&str>) {
pub fn add_source_mapping_for_name(&mut self, output: &[u8], span: Span, name: &str) {
// SAFETY: search original string by span.
let original_name =
unsafe { self.original_source.get_unchecked(span.start as usize..span.end as usize) };
// The token name should be original name.
// If it hasn't change, name should be `None` to reduce `SourceMap` size.
let token_name = if original_name == name { None } else { Some(original_name.into()) };
self.add_source_mapping(output, span.start, token_name);
}
pub fn add_source_mapping(&mut self, output: &[u8], position: u32, name: Option<Arc<str>>) {
if self.enable_sourcemap {
if matches!(self.last_position, Some(last_position) if last_position >= position) {
return;
}
let (original_line, original_column) = self.search_original_line_and_column(position);
self.update_generated_line_and_column(output);
let name_id = name.map(|s| self.sourcemap_builder.add_name(s));
let name_id = name.map(|s| self.sourcemap_builder.add_name(&s));
self.sourcemap_builder.add_token(
self.generated_line,
self.generated_column,
@ -349,4 +380,24 @@ mod test {
create_mappings("abc\r\n", 1, 0);
create_mappings("ÖÖ\nÖ\nÖÖÖ", 2, 3);
}
#[test]
fn add_source_mapping_for_name() {
let output = "ac".as_bytes();
let mut builder = SourcemapBuilder::default();
builder.with_name_and_source("x.js", "ab");
builder.add_source_mapping_for_name(output, Span::new(0, 1), "a");
builder.add_source_mapping_for_name(output, Span::new(1, 2), "c");
let sm = builder.into_sourcemap().unwrap();
// The name `a` not change.
assert_eq!(
sm.get_source_view_token(0_u32).as_ref().and_then(|token| token.get_name()),
None
);
// The name `b` -> `c`, save `b` to token.
assert_eq!(
sm.get_source_view_token(1_u32).as_ref().and_then(|token| token.get_name()),
Some("b")
);
}
}

View file

@ -72,6 +72,10 @@ impl SourceMap {
self.tokens.get(index as usize)
}
pub fn get_source_view_token(&self, index: u32) -> Option<SourceViewToken<'_>> {
self.tokens.get(index as usize).map(|token| SourceViewToken::new(token, self))
}
/// Get raw tokens.
pub fn get_tokens(&self) -> impl Iterator<Item = &Token> {
self.tokens.iter()