Skip to content

Commit

Permalink
Avoid clonning input js code if status is notmodified (#112)
Browse files Browse the repository at this point in the history
* Avoid clonning input code if status is notmodified

* return original code if notmodified

* remove TransformOutputWithStatus struct

* clean up

* clean up

* clean up chain_source_maps method

* Fix conflict
  • Loading branch information
iunanua authored Jan 13, 2025
1 parent 8acf326 commit f91ec60
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 83 deletions.
9 changes: 8 additions & 1 deletion main.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,14 @@ class NonCacheRewriter {
}

rewrite (code, file) {
return this.nativeRewriter.rewrite(code, file)
const response = this.nativeRewriter.rewrite(code, file)

// rewrite returns an empty content when for the 'notmodified' status
if (response?.metrics?.status === 'notmodified') {
response.content = code
}

return response
}

csiMethods () {
Expand Down
8 changes: 7 additions & 1 deletion src/lib_wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,13 @@ impl Rewriter {

rewrite_js(code, &file, &self.config, &source_map_reader)
.map(|result| Result {
content: print_js(&result, &self.config),
content: print_js(
&result.code,
&result.source_map,
&result.original_source_map,
&self.config,
)
.into_owned(),
metrics: get_metrics(result.transform_status, &file),
literals_result: result.literals_result,
})
Expand Down
104 changes: 47 additions & 57 deletions src/rewriter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use anyhow::{Error, Result};
use base64::{engine::general_purpose::STANDARD, Engine as _};
use log::debug;
use std::{
borrow::Cow,
collections::HashMap,
io::Read,
path::{Path, PathBuf},
Expand All @@ -25,7 +26,7 @@ use std::{
use swc::{
config::{IsModule, SourceMapsConfig},
sourcemap::{decode, decode_data_url, DecodedMap, SourceMap, SourceMapBuilder},
try_with_handler, Compiler, HandlerOpts, PrintArgs, SwcComments, TransformOutput,
try_with_handler, Compiler, HandlerOpts, PrintArgs, SwcComments,
};
use swc_common::{
comments::Comments,
Expand Down Expand Up @@ -53,12 +54,6 @@ pub struct OriginalSourceMap {
pub source_map_comment: Option<String>,
}

pub struct TransformOutputWithStatus {
pub output: TransformOutput,
pub status: TransformStatus,
pub literals_result: Option<LiteralsResult>,
}

pub struct Config {
pub chain_source_map: bool,
pub print_comments: bool,
Expand Down Expand Up @@ -99,42 +94,30 @@ pub fn rewrite_js<R: Read>(
.cm
.new_source_file(Arc::new(FileName::Real(PathBuf::from(file))), code);

let program = parse_js(&source_file, handler, &compiler)?;

// extract sourcemap before printing otherwise comments are consumed
// and looks like it is not possible to read them after compiler.print() invocation
let original_map = extract_source_map(file, compiler.comments(), file_reader);

let result = transform_js(program, &source_file, file, config, &compiler);

result.map(|transformed| RewrittenOutput {
code: transformed.output.code,
source_map: transformed.output.map.unwrap_or_default(),
original_source_map: original_map,
transform_status: Some(transformed.status),
literals_result: transformed.literals_result,
})
parse_js(&source_file, handler, &compiler)
.and_then(|program| transform_js(program, file, file_reader, config, &compiler))
})
}

pub fn print_js(output: &RewrittenOutput, config: &Config) -> String {
let mut final_source_map: String = String::from(&output.source_map);
let original_source_map = &output.original_source_map;
if config.chain_source_map {
final_source_map = chain_source_maps(&output.source_map, &original_source_map.source)
.unwrap_or_else(|_| String::from(&output.source_map));
}
pub fn print_js<'a>(
code: &'a str,
source_map: &str,
original_source_map: &OriginalSourceMap,
config: &Config,
) -> Cow<'a, str> {
let final_source_map = chain_source_maps(source_map, &original_source_map.source, config)
.unwrap_or_else(|| String::from(source_map));

let final_code = if config.print_comments {
match &original_source_map.source_map_comment {
Some(comment) => {
debug!("Replacing original sourceMappingUrl comment: {comment}");
output.code.replace(comment.as_str(), "")
code.replace(comment.as_str(), "").into()
}
_ => output.code.clone(),
_ => code.into(),
}
} else {
output.code.clone()
code.into()
};

if final_source_map.is_empty() {
Expand All @@ -149,6 +132,7 @@ pub fn print_js(output: &RewrittenOutput, config: &Config) -> String {
SOURCE_MAP_URL,
STANDARD.encode(final_source_map)
)
.into()
}
}

Expand Down Expand Up @@ -187,13 +171,13 @@ fn parse_js(
)
}

fn transform_js(
fn transform_js<R: Read>(
mut program: Program,
source_file: &SourceFile,
file: &str,
file_reader: &impl FileReader<R>,
config: &Config,
compiler: &Compiler,
) -> Result<TransformOutputWithStatus, Error> {
) -> Result<RewrittenOutput, Error> {
let mut transform_status = TransformStatus::not_modified(config);

let mut block_transform_visitor = BlockTransformVisitor::default(&mut transform_status, config);
Expand All @@ -212,22 +196,29 @@ fn transform_js(

match transform_status.status {
Status::Modified => {
// extract sourcemap before printing otherwise comments are consumed
// and looks like it is not possible to read them after compiler.print() invocation
let original_source_map = extract_source_map(file, compiler.comments(), file_reader);

compiler
.print(&program, print_args)
.map(|output| TransformOutputWithStatus {
output,
status: transform_status,
.map(|output| RewrittenOutput {
code: output.code,
source_map: output.map.unwrap_or_default(),
original_source_map,
transform_status: Some(transform_status),
literals_result,
})
}

Status::NotModified => Ok(TransformOutputWithStatus {
output: TransformOutput {
code: source_file.src.to_string(),
map: None,
output: None,
Status::NotModified => Ok(RewrittenOutput {
code: String::default(),
source_map: String::default(),
original_source_map: OriginalSourceMap {
source: None,
source_map_comment: None,
},
status: transform_status,
transform_status: Some(transform_status),
literals_result,
}),

Expand All @@ -242,14 +233,15 @@ fn transform_js(
}

fn chain_source_maps(
source_map: &String,
source_map: &str,
original_map: &Option<SourceMap>,
) -> Result<String, Error> {
debug!("Chaining sourcemaps");
config: &Config,
) -> Option<String> {
config.chain_source_map.then(|| {
debug!("Chaining sourcemaps");

if let Some(new_source) = parse_source_map(Some(source_map.as_str())) {
match original_map {
Some(original_source) => {
original_map.as_ref().and_then(|original_source| {
parse_source_map(Some(source_map)).and_then(|new_source| {
let mut builder = SourceMapBuilder::new(None);
let mut sources: HashMap<String, u32> = HashMap::new();
let mut names: HashMap<String, u32> = HashMap::new();
Expand Down Expand Up @@ -286,6 +278,7 @@ fn chain_source_maps(
);
}
}

let mut source_map_output: Vec<u8> = vec![];
builder
.into_sourcemap()
Expand All @@ -296,14 +289,11 @@ fn chain_source_maps(
})
.map_err(|err| {
debug!("Error chaining sourcemaps {err:?}");
Error::new(err)
})
}
None => Result::Ok(String::from(source_map)),
}
} else {
Result::Ok(String::from(source_map))
}
.ok()
})
})
})?
}

fn extract_source_map<R: Read>(
Expand Down
11 changes: 7 additions & 4 deletions src/tests/binary_expression_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,17 @@ mod tests {

use anyhow::Error;

use crate::{rewriter::debug_js, tests::rewrite_js};
use crate::{
rewriter::debug_js,
tests::{assert_not_modified, rewrite_js},
};

#[test]
fn test_simple_plus_literal() -> Result<(), String> {
let original_code = "{const result = 'a' + 'b'}".to_string();
let js_file = "test.js".to_string();
let rewritten = rewrite_js(original_code, js_file).map_err(|e| e.to_string())?;
assert_that(&rewritten.code).contains("const result = 'a' + 'b'");
assert_not_modified(&rewritten);
Ok(())
}

Expand All @@ -26,7 +29,7 @@ mod tests {
let original_code = "{const result = 'a' + 'b' + 'c'}".to_string();
let js_file = "test.js".to_string();
let rewritten = rewrite_js(original_code, js_file).map_err(|e| e.to_string())?;
assert_that(&rewritten.code).contains("const result = 'a' + 'b' + 'c'");
assert_not_modified(&rewritten);
Ok(())
}

Expand All @@ -45,7 +48,7 @@ mod tests {
let original_code = "{const result = 1 + 2}".to_string();
let js_file = "test.js".to_string();
let rewritten = rewrite_js(original_code, js_file).map_err(|e| e.to_string())?;
assert_that(&rewritten.code).contains("const result = 1 + 2");
assert_not_modified(&rewritten);
Ok(())
}

Expand Down
12 changes: 12 additions & 0 deletions src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
use crate::{
rewriter::{Config, RewrittenOutput},
telemetry::TelemetryVerbosity,
transform::transform_status::Status,
util::DefaultFileReader,
visitor::csi_methods::{CsiMethod, CsiMethods},
};
use anyhow::Error;
use speculoos::{assert_that, prelude::BooleanAssertions};
use std::path::PathBuf;

mod arrow_func_tests;
Expand Down Expand Up @@ -145,3 +147,13 @@ fn csi_op_from_str(src: &str, dst: Option<&str>) -> CsiMethod {
};
CsiMethod::new(String::from(src), dst_string, true, false)
}

fn assert_not_modified(output: &RewrittenOutput) {
assert_that(
&output
.transform_status
.as_ref()
.is_some_and(|transform_status| transform_status.status == Status::NotModified),
)
.is_true();
}
24 changes: 17 additions & 7 deletions src/tests/source_map_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ mod tests {
use swc::sourcemap::{decode_data_url, DecodedMap};

use crate::{
rewriter::{print_js, rewrite_js, RewrittenOutput},
rewriter::{print_js, rewrite_js, Config, RewrittenOutput},
tests::{
get_chained_and_print_comments_config, get_default_config, get_test_resources_folder,
},
Expand Down Expand Up @@ -116,10 +116,20 @@ mod tests {
}
}

fn print(result: &RewrittenOutput, config: &Config) -> String {
print_js(
&result.code,
&result.source_map,
&result.original_source_map,
config,
)
.into_owned()
}

#[test]
fn test_source_maps_unchained_embedded() -> Result<(), String> {
let rewritten = get_rewritten_js("StrUtil_embedded.js")?;
let result = print_js(&rewritten, &get_default_config(false));
let result = print(&rewritten, &get_default_config(false));
assert_that(&result).contains(SOURCE_MAP_URL);
check_sourcemap_tokens(result, UNCHAINED_TOKENS.to_vec());
Ok(())
Expand All @@ -128,7 +138,7 @@ mod tests {
#[test]
fn test_source_maps_unchained_external() -> Result<(), String> {
let rewritten = get_rewritten_js("StrUtil_external.js")?;
let result = print_js(&rewritten, &get_default_config(false));
let result = print(&rewritten, &get_default_config(false));
assert_that(&result).contains(SOURCE_MAP_URL);
check_sourcemap_tokens(result, UNCHAINED_TOKENS.to_vec());
Ok(())
Expand All @@ -137,7 +147,7 @@ mod tests {
#[test]
fn test_source_maps_unchained_without_original_source_map() -> Result<(), String> {
let rewritten = get_rewritten_js("StrUtil_without_sm.js")?;
let result = print_js(&rewritten, &get_default_config(false));
let result = print(&rewritten, &get_default_config(false));
assert_that(&result).contains(SOURCE_MAP_URL);
check_sourcemap_tokens(result, UNCHAINED_TOKENS.to_vec());
Ok(())
Expand All @@ -146,7 +156,7 @@ mod tests {
#[test]
fn test_source_maps_chained_embedded() -> Result<(), String> {
let rewritten = get_rewritten_js("StrUtil_embedded.js")?;
let result = print_js(&rewritten, &get_chained_and_print_comments_config());
let result = print(&rewritten, &get_chained_and_print_comments_config());
assert_that(&result).contains(SOURCE_MAP_URL);
check_sourcemap_tokens(result, CHAINED_TOKENS.to_vec());
Ok(())
Expand All @@ -155,7 +165,7 @@ mod tests {
#[test]
fn test_source_maps_chained_external() -> Result<(), String> {
let rewritten = get_rewritten_js("StrUtil_external.js")?;
let result = print_js(&rewritten, &get_chained_and_print_comments_config());
let result = print(&rewritten, &get_chained_and_print_comments_config());
assert_that(&result).contains(SOURCE_MAP_URL);
check_sourcemap_tokens(result, CHAINED_TOKENS.to_vec());
Ok(())
Expand All @@ -164,7 +174,7 @@ mod tests {
#[test]
fn test_source_maps_chained_without_original_source_map() -> Result<(), String> {
let rewritten = get_rewritten_js("StrUtil_without_sm.js")?;
let result = print_js(&rewritten, &get_chained_and_print_comments_config());
let result = print(&rewritten, &get_chained_and_print_comments_config());
assert_that(&result).contains(SOURCE_MAP_URL);
check_sourcemap_tokens(result, UNCHAINED_TOKENS.to_vec());
Ok(())
Expand Down
Loading

0 comments on commit f91ec60

Please sign in to comment.