mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
fix(codegen): sourcemap token name should be original name (#2843)
close https://github.com/oxc-project/oxc/issues/2753.
This commit is contained in:
parent
b199cb89a2
commit
6177c2f7ef
4 changed files with 67 additions and 12 deletions
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Reference in a new issue