Skip to content

Commit

Permalink
read file from memory + recover if fail; add mangler test
Browse files Browse the repository at this point in the history
  • Loading branch information
Boshen committed Jul 16, 2024
1 parent 23d2ce1 commit cf20a8b
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 44 deletions.
26 changes: 26 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ test = false
doctest = false

[dependencies]
oxc = { path = "../oxc/crates/oxc", features = ["transformer", "isolated_declarations", "codegen"] }
oxc = { path = "../oxc/crates/oxc", features = ["transformer", "isolated_declarations", "codegen", "minifier"] }
walkdir = "2.5.0"
similar = "2.5.0"
console = "0.15.8"
url = "2.5.2"
ureq = "2.9.7"
anyhow = "1"

[profile.release]
opt-level = 3
Expand Down
29 changes: 12 additions & 17 deletions src/codegen.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{fs, path::Path};

use crate::{NodeModulesRunner, Source};
use anyhow::Result;

use oxc::{
allocator::Allocator,
Expand All @@ -9,40 +9,35 @@ use oxc::{
span::SourceType,
};

pub struct CodegenRunner {
runner: NodeModulesRunner,
}
use crate::{NodeModulesRunner, Source};

impl CodegenRunner {
pub fn new() -> Self {
Self { runner: NodeModulesRunner::new() }
}
pub struct CodegenRunner;

pub fn run(self) {
for source in &self.runner.files {
self.test(source);
impl CodegenRunner {
pub fn run(self, runner: &NodeModulesRunner) -> Result<()> {
println!("Running Codegen");
for source in &runner.files {
self.test(source)?;
}
NodeModulesRunner::run_runtime_test();
NodeModulesRunner::run_runtime_test()
}

fn test(&self, source: &Source) {
fn test(&self, source: &Source) -> Result<()> {
let Source { path, source_type, source_text } = source;
if source_text.starts_with("// @flow") {
return;
}
let source_text2 = self.codegen(path, source_text, *source_type);
// Idempotency test
let source_text3 = self.codegen(path, &source_text2, *source_type);

if source_text2 != source_text3 {
NodeModulesRunner::print_diff(&source_text2, &source_text3);
panic!("Codegen idempotency test failed: {path:?}");
anyhow::bail!("Codegen idempotency test failed: {path:?}");
}

// Write js files for runtime test
if source_type.is_javascript() {
fs::write(path, source_text3).unwrap();
}
Ok(())
}

fn codegen(&self, path: &Path, source_text: &str, source_type: SourceType) -> String {
Expand Down
19 changes: 16 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

pub mod codegen;
pub mod isolated_declarations;
pub mod mangler;
pub mod transform;

use std::{fs, os::unix::process::CommandExt, path::PathBuf, process::Command};
use std::{fs, path::PathBuf, process::Command};

use anyhow::{Context, Result};
use console::Style;
use similar::{ChangeTag, TextDiff};
use walkdir::WalkDir;
Expand Down Expand Up @@ -41,14 +43,25 @@ impl NodeModulesRunner {
continue;
};
let source_text = fs::read_to_string(path).unwrap();
if source_text.starts_with("// @flow") {
continue;
}
files.push(Source { path: path.to_path_buf(), source_type, source_text });
}
println!("Collected {} files.", files.len());
Self { files }
}

pub fn run_runtime_test() {
Command::new("pnpm").arg("test").exec();
pub fn recover(self) {
for source in self.files {
fs::write(source.path, source.source_text).unwrap();
}
}

pub fn run_runtime_test() -> Result<()> {
println!("pnpm test");
Command::new("pnpm").arg("test").status().context("pnpm test failed")?;
Ok(())
}

pub fn print_diff(origin_string: &str, expected_string: &str) {
Expand Down
21 changes: 17 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
use anyhow::Result;

use monitor_oxc::{
codegen::CodegenRunner, isolated_declarations::test_isolated_declarations,
transform::TransformRunner,
mangler::ManglerRunner, transform::TransformRunner, NodeModulesRunner,
};

fn main() {
CodegenRunner::new().run();
TransformRunner::new().run();
fn main() -> Result<()> {
let node_modules_runner = NodeModulesRunner::new();
let result = run(&node_modules_runner);
if result.is_err() {
node_modules_runner.recover();
}
result
}

fn run(node_modules_runner: &NodeModulesRunner) -> Result<()> {
CodegenRunner.run(node_modules_runner)?;
TransformRunner.run(node_modules_runner)?;
ManglerRunner.run(node_modules_runner)?;
test_isolated_declarations();
Ok(())
}
67 changes: 67 additions & 0 deletions src/mangler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use std::{fs, path::Path};

use anyhow::Result;

use oxc::{
allocator::Allocator,
codegen::{CodeGenerator, CommentOptions},
mangler::ManglerBuilder,
parser::{Parser, ParserReturn},
span::SourceType,
};

use crate::{NodeModulesRunner, Source};

pub struct ManglerRunner;

impl ManglerRunner {
pub fn run(self, runner: &NodeModulesRunner) -> Result<()> {
println!("Running Mangler");
for source in &runner.files {
self.test(source)?;
}
NodeModulesRunner::run_runtime_test()
}

fn test(&self, source: &Source) -> Result<()> {
let Source { path, source_type, source_text } = source;
let source_text2 = self.mangle(path, source_text, *source_type);

// Idempotency test
let source_text3 = self.mangle(path, &source_text2, *source_type);
if source_text2 != source_text3 {
NodeModulesRunner::print_diff(&source_text2, &source_text3);
anyhow::bail!("Mangler idempotency test failed: {path:?}");
}

// Write js files for runtime test
if source_type.is_javascript() {
fs::write(path, source_text3).unwrap();
}
Ok(())
}

fn mangle(&self, path: &Path, source_text: &str, source_type: SourceType) -> String {
let allocator = Allocator::default();
let ParserReturn { program, errors, trivias, .. } =
Parser::new(&allocator, source_text, source_type)
.allow_return_outside_function(true)
.parse();
if !errors.is_empty() {
for error in errors {
println!("{:?}", error.with_source_code(source_text.to_string()));
}
panic!("Expect no parse errors: {path:?}");
}
let mangler = ManglerBuilder.build(&program);
CodeGenerator::new()
.enable_comment(
source_text,
trivias,
CommentOptions { preserve_annotate_comments: true },
)
.with_mangler(Some(mangler))
.build(&program)
.source_text
}
}
36 changes: 17 additions & 19 deletions src/transform.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{fs, path::Path};

use crate::{NodeModulesRunner, Source};
use anyhow::Result;

use oxc::{
allocator::Allocator,
Expand All @@ -10,32 +10,29 @@ use oxc::{
transformer::{TransformOptions, Transformer},
};

pub struct TransformRunner {
runner: NodeModulesRunner,
}
use crate::{NodeModulesRunner, Source};

impl TransformRunner {
pub fn new() -> Self {
Self { runner: NodeModulesRunner::new() }
}
pub struct TransformRunner;

pub fn run(self) {
for source in &self.runner.files {
self.test(source);
impl TransformRunner {
pub fn run(self, runner: &NodeModulesRunner) -> Result<()> {
println!("Running Codegen");
for source in &runner.files {
self.test(source)?;
}
NodeModulesRunner::run_runtime_test();
NodeModulesRunner::run_runtime_test()
}

fn test(&self, source: &Source) {
fn test(&self, source: &Source) -> Result<()> {
let Source { path, source_type, source_text } = source;
let source_text2 = self.transform(path, source_text, *source_type);
let source_text2 = self.transform(path, source_text, *source_type)?;

// Idempotency test
let source_text3 = self.transform(path, &source_text2, *source_type);
let source_text3 = self.transform(path, &source_text2, *source_type)?;

if source_text2 != source_text3 {
NodeModulesRunner::print_diff(&source_text2, &source_text3);
panic!("Transform idempotency test failed: {path:?}");
anyhow::bail!("Transform idempotency test failed: {path:?}");
}

// Write js files for runtime test
Expand All @@ -54,14 +51,15 @@ impl TransformRunner {
// Maybe .d.ts file
}
}
Ok(())
}

pub fn transform(
&self,
source_path: &Path,
source_text: &str,
source_type: SourceType,
) -> String {
) -> Result<String> {
let allocator = Allocator::default();

let ParserReturn { mut program, errors, trivias, .. } =
Expand All @@ -72,7 +70,7 @@ impl TransformRunner {
for error in errors {
println!("{:?}", error.with_source_code(source_text.to_string()));
}
panic!("Expect no parse errors: {source_path:?}");
anyhow::bail!("Expect no parse errors: {source_path:?}");
}

Transformer::new(
Expand All @@ -94,6 +92,6 @@ impl TransformRunner {
.build(&program)
.source_text;

source.replace(".mts", "").replace(".cts", "").replace(".ts", "")
Ok(source)
}
}

0 comments on commit cf20a8b

Please sign in to comment.