From 3548cf4a59e9731681d3818ea5ffdd25ea36c82c Mon Sep 17 00:00:00 2001 From: Boshen <1430279+Boshen@users.noreply.github.com> Date: Mon, 18 Aug 2025 08:33:48 +0000 Subject: [PATCH] refactor(sourcemap): improve sourcemap visualization code (#13177) --- Cargo.lock | 13 ++-- crates/oxc_codegen/Cargo.toml | 1 - crates/oxc_codegen/examples/codegen.rs | 33 +++++++--- crates/oxc_codegen/examples/sourcemap.rs | 61 ------------------- .../integrations/replace_global_defines.rs | 2 +- 5 files changed, 30 insertions(+), 80 deletions(-) delete mode 100644 crates/oxc_codegen/examples/sourcemap.rs diff --git a/Cargo.lock b/Cargo.lock index bcd18c4321ffc..8bdf2f54741e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -300,7 +300,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" dependencies = [ "lazy_static", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -309,7 +309,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -1832,7 +1832,6 @@ dependencies = [ name = "oxc_codegen" version = "0.82.2" dependencies = [ - "base64", "bitflags 2.9.2", "cow-utils", "dragonbox_ecma", @@ -2305,9 +2304,9 @@ dependencies = [ [[package]] name = "oxc_sourcemap" -version = "4.0.5" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6057a9bbd4a84bb4146539123642ee66e0f5ac700b0fcddd193cabcb2e0460" +checksum = "d5e78344e5a6cdd74250bc9bb144a4c3215b6107fe4fd47973f4bd175372ccb2" dependencies = [ "base64-simd", "napi", @@ -3226,7 +3225,7 @@ dependencies = [ "getrandom 0.3.3", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -3739,7 +3738,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] diff --git a/crates/oxc_codegen/Cargo.toml b/crates/oxc_codegen/Cargo.toml index 76809c4c6531e..c5b66a3be5153 100644 --- a/crates/oxc_codegen/Cargo.toml +++ b/crates/oxc_codegen/Cargo.toml @@ -37,7 +37,6 @@ nonmax = { workspace = true } rustc-hash = { workspace = true } [dev-dependencies] -base64 = { workspace = true } insta = { workspace = true } oxc_parser = { workspace = true } pico-args = { workspace = true } diff --git a/crates/oxc_codegen/examples/codegen.rs b/crates/oxc_codegen/examples/codegen.rs index c942b697ac53d..f6ab169786019 100644 --- a/crates/oxc_codegen/examples/codegen.rs +++ b/crates/oxc_codegen/examples/codegen.rs @@ -18,12 +18,14 @@ use std::path::Path; +use pico_args::Arguments; + use oxc_allocator::Allocator; use oxc_ast::ast::Program; -use oxc_codegen::{Codegen, CodegenOptions}; +use oxc_codegen::{Codegen, CodegenOptions, CodegenReturn}; use oxc_parser::{ParseOptions, Parser}; +use oxc_sourcemap::SourcemapVisualizer; use oxc_span::SourceType; -use pico_args::Arguments; // Instruction: // create a `test.js`, @@ -36,9 +38,12 @@ fn main() -> std::io::Result<()> { let twice = args.contains("--twice"); let minify = args.contains("--minify"); - let name = args.free_from_str().unwrap_or_else(|_| "test.js".to_string()); + let sourcemap = args.contains("--sourcemap"); + let name = args.free_from_str().unwrap_or_else(|_| "test.js".to_string()); let path = Path::new(&name); + let sourcemap = sourcemap.then_some(path); + let source_text = std::fs::read_to_string(path)?; let source_type = SourceType::from_path(path).unwrap(); let mut allocator = Allocator::default(); @@ -46,7 +51,7 @@ fn main() -> std::io::Result<()> { // First round: parse and generate let printed = { let program = parse(&allocator, &source_text, source_type); - codegen(&program, minify) + codegen(&program, minify, sourcemap) }; println!("First time:"); println!("{printed}"); @@ -58,7 +63,7 @@ fn main() -> std::io::Result<()> { let program = parse(&allocator, &printed, source_type); println!("Second time:"); - let printed2 = codegen(&program, minify); + let printed2 = codegen(&program, minify, None); println!("{printed2}"); // Check syntax error parse(&allocator, &printed2, source_type); @@ -87,9 +92,17 @@ fn parse<'a>( } /// Generate JavaScript code from an AST -fn codegen(program: &Program<'_>, minify: bool) -> String { - Codegen::new() - .with_options(if minify { CodegenOptions::minify() } else { CodegenOptions::default() }) - .build(program) - .code +fn codegen(program: &Program<'_>, minify: bool, source_map_path: Option<&Path>) -> String { + let mut options = if minify { CodegenOptions::minify() } else { CodegenOptions::default() }; + options.source_map_path = source_map_path.map(Path::to_path_buf); + + let CodegenReturn { code, map, .. } = Codegen::new().with_options(options).build(program); + + if let Some(map) = map { + let visualizer = SourcemapVisualizer::new(&code, &map); + println!("{}", visualizer.get_url()); + println!("{}", visualizer.get_text()); + } + + code } diff --git a/crates/oxc_codegen/examples/sourcemap.rs b/crates/oxc_codegen/examples/sourcemap.rs deleted file mode 100644 index 37a4f3c4fc465..0000000000000 --- a/crates/oxc_codegen/examples/sourcemap.rs +++ /dev/null @@ -1,61 +0,0 @@ -#![expect(clippy::print_stdout)] -//! # Source Map Generation Example -//! -//! This example demonstrates how to generate source maps alongside JavaScript code. -//! It generates a visualization URL for inspecting the source map. -//! -//! ## Usage -//! -//! Create a `test.js` file and run: -//! ```bash -//! cargo run -p oxc_codegen --example sourcemap [filename] -//! ``` - -use std::{env, path::Path}; - -use base64::{Engine, prelude::BASE64_STANDARD}; -use oxc_allocator::Allocator; -use oxc_codegen::{Codegen, CodegenOptions, CodegenReturn}; -use oxc_parser::Parser; -use oxc_span::SourceType; - -// Instruction: -// 1. create a `test.js` -// 2. run `cargo run -p oxc_codegen --example sourcemap` - -/// Generate source maps and provide a visualization URL -fn main() -> std::io::Result<()> { - let name = env::args().nth(1).unwrap_or_else(|| "test.js".to_string()); - let path = Path::new(&name); - let source_text = std::fs::read_to_string(path)?; - let source_type = SourceType::from_path(path).unwrap(); - let allocator = Allocator::default(); - let ret = Parser::new(&allocator, &source_text, source_type).parse(); - - // Handle parsing errors - if !ret.errors.is_empty() { - for error in ret.errors { - let error = error.with_source_code(source_text.clone()); - println!("{error:?}"); - } - return Ok(()); - } - - // Generate code with source map - let CodegenReturn { code, map, .. } = Codegen::new() - .with_options(CodegenOptions { - source_map_path: Some(path.to_path_buf()), - ..CodegenOptions::default() - }) - .build(&ret.program); - - // Create visualization URL if source map was generated - if let Some(source_map) = map { - let result = source_map.to_json_string(); - let hash = - BASE64_STANDARD.encode(format!("{}\0{}{}\0{}", code.len(), code, result.len(), result)); - println!("https://evanw.github.io/source-map-visualization/#{hash}"); - } - - Ok(()) -} diff --git a/crates/oxc_transformer_plugins/tests/integrations/replace_global_defines.rs b/crates/oxc_transformer_plugins/tests/integrations/replace_global_defines.rs index 241c5749a0223..c478145695b0b 100644 --- a/crates/oxc_transformer_plugins/tests/integrations/replace_global_defines.rs +++ b/crates/oxc_transformer_plugins/tests/integrations/replace_global_defines.rs @@ -274,6 +274,6 @@ log(__MEMBER__); let output = result.code; let output_map = result.map.unwrap(); let visualizer = SourcemapVisualizer::new(&output, &output_map); - let snapshot = visualizer.into_visualizer_text(); + let snapshot = visualizer.get_text(); insta::assert_snapshot!("test_sourcemap", snapshot); }