Skip to content

Commit 04b948c

Browse files
save
Signed-off-by: Nikola Hristov <Nikola@PlayForm.Cloud>
1 parent 8e80a91 commit 04b948c

8 files changed

Lines changed: 170 additions & 144 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[[bin]]
22
name = "Rest"
3-
path = "Source/Binary.rs"
3+
path = "Source/Library.rs"
44

55
[build-dependencies]
66
serde = { workspace = true, features = ["derive"] }

Source/Binary.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
#![allow(non_snake_case)]
22

3-
//! Binary entry point for Rest.
4-
5-
use Library::Fn as Struct;
6-
73
#[tokio::main]
8-
async fn main() { (Struct::Binary::Command::Struct::Fn().Fn)().await }
4+
async fn main() { (crate::Binar::Binary::Command::Struct::Fn().Fn)().await }

Source/Fn/OXC/Codegen.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,11 @@ pub struct CodegenResult {
4646
pub code_len:usize,
4747
}
4848

49-
/// Post-process generated JavaScript to match VSCode's static class property format.
50-
/// Converts `static x = expr;` into `static { this.x = expr; }`.
49+
/// Post-process generated JavaScript to match VSCode's static class property
50+
/// format. Converts `static x = expr;` into `static { this.x = expr; }`.
5151
/// This is needed because OXC 0.48's class properties plugin does not emit
5252
/// legacy static initializer blocks by default.
53-
fn transform_static_class_properties(code: &str) -> String {
53+
fn transform_static_class_properties(code:&str) -> String {
5454
// This regex matches: static <name> = <expression>;
5555
// Captures the property name and the initializer expression.
5656
let re = match regex::Regex::new(r"(?m)^\s*static\s+([a-zA-Z_$][\w$]*)\s*=\s*([^;]+);") {
@@ -59,7 +59,7 @@ fn transform_static_class_properties(code: &str) -> String {
5959
// If regex compilation fails, return original code and log.
6060
error!("transform_static_class_properties: regex compile error: {}", e);
6161
return code.to_string();
62-
}
62+
},
6363
};
6464
re.replace_all(code, "static { this.$1 = $2; }").into_owned()
6565
}
@@ -119,7 +119,7 @@ pub fn codegen<'a>(
119119
info!("[Codegen #{codegen_id}] SUCCESS: Generated {} bytes", code_len);
120120
// Transform OXC output to match VSCode static class property format
121121
let transformed_code = transform_static_class_properties(&code);
122-
Ok(CodegenResult { code: transformed_code, code_len })
122+
Ok(CodegenResult { code:transformed_code, code_len })
123123
}
124124

125125
/// Write the generated code to a file

Source/Fn/OXC/Compiler.rs

Lines changed: 121 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -173,128 +173,128 @@ impl Compiler {
173173
/// Result containing the output file path
174174
#[tracing::instrument(skip(self, input))]
175175
pub fn compile_file_to(
176-
&self,
177-
file_path:&str,
178-
input:String,
179-
output_path:&Path,
180-
use_define_for_class_fields:bool,
176+
&self,
177+
file_path:&str,
178+
input:String,
179+
output_path:&Path,
180+
use_define_for_class_fields:bool,
181181
) -> anyhow::Result<String> {
182-
let compile_id = COMPILE_ID.fetch_add(1, Ordering::SeqCst);
183-
let begin = Instant::now();
184-
185-
info!(
186-
"[Compile #{compile_id}] START compile_file_to: {} -> {}",
187-
file_path,
188-
output_path.display()
189-
);
190-
trace!(
191-
"[Compile #{compile_id}] Input size: {} bytes, use_define_for_class_fields={}",
192-
input.len(),
193-
use_define_for_class_fields
194-
);
195-
196-
// CRITICAL FIX: Wrap entire compilation in its own scope to ensure
197-
// the allocator is dropped before the next file is processed.
198-
// This prevents OXC internal state corruption when processing
199-
// multiple files sequentially.
200-
let codegen_result = {
201-
// Parse the TypeScript source
202-
info!("[Compile #{compile_id}] Step 1/4: Parsing {}", file_path);
203-
let parse_start = Instant::now();
204-
let parser_config = self.get_parser_config();
205-
let mut parse_result = Parser::parse(&input, file_path, &parser_config)
206-
.map_err(|errors| anyhow::anyhow!("Parse errors: {:?}", errors))?;
207-
info!(
208-
"[Compile #{compile_id}] Step 1/4 complete: Parse in {:?}",
209-
parse_start.elapsed()
210-
);
211-
212-
debug!(
213-
"[Compile #{compile_id}] Memory addresses: allocator={:p}, program={:p}",
214-
&parse_result.allocator, &parse_result.program
215-
);
216-
trace!(
217-
"[Compile #{compile_id}] AST body slice: ptr={:p}, len={}",
218-
parse_result.program.body.as_ptr(),
219-
parse_result.program.body.len()
220-
);
221-
222-
// Transform the AST - borrow program mutably, don't move it out
223-
info!("[Compile #{compile_id}] Step 2/4: Transforming");
224-
let transform_start = Instant::now();
225-
let mut transformer_config = self.get_transformer_config();
226-
transformer_config.use_define_for_class_fields = use_define_for_class_fields;
227-
228-
// SAFETY: We borrow program with 'static lifetime from parse_result.
229-
// This is safe because:
230-
// 1. parse_result stays in scope for the entire inner block
231-
// 2. The program and allocator are dropped together when parse_result is
232-
// dropped
233-
// 3. We never use program after parse_result is dropped
234-
let program = unsafe {
235-
std::mem::transmute::<&mut oxc_ast::ast::Program<'static>, &mut oxc_ast::ast::Program<'_>>(
236-
&mut parse_result.program,
237-
)
238-
};
239-
240-
let source_type = oxc_span::SourceType::from_path(file_path).unwrap_or(oxc_span::SourceType::ts());
241-
242-
Transformer::transform(&parse_result.allocator, program, file_path, source_type, &transformer_config)
243-
.map_err(|errors| anyhow::anyhow!("Transform errors: {:?}", errors))?;
244-
info!(
245-
"[Compile #{compile_id}] Step 2/4 complete: Transform in {:?}",
246-
transform_start.elapsed()
247-
);
248-
trace!(
249-
"[Compile #{compile_id}] Program after transform - body ptr: {:p}",
250-
program.body.as_ptr()
251-
);
252-
253-
// Generate code - parse_result still alive
254-
info!("[Compile #{compile_id}] Step 3/4: Codegen");
255-
let codegen_start = Instant::now();
256-
let codegen_config = self.get_codegen_config();
257-
let codegen_result = Codegen::codegen(&parse_result.allocator, program, source_type, &codegen_config)
258-
.map_err(|e| anyhow::anyhow!("Codegen error: {}", e))?;
259-
info!(
260-
"[Compile #{compile_id}] Step 3/4 complete: Codegen in {:?}, output={}(bytes)",
261-
codegen_start.elapsed(),
262-
codegen_result.code.len()
263-
);
264-
265-
// Force drop of parse_result to ensure allocator is freed
266-
// before returning from this scope
267-
let _ = program;
268-
// parse_result will be dropped at end of scope
269-
codegen_result
270-
}; // parse_result and allocator dropped here - critical for preventing segfault
271-
272-
// Create parent directories if they don't exist
273-
if let Some(parent) = output_path.parent() {
274-
std::fs::create_dir_all(parent)?;
275-
}
276-
277-
// Write to the specified output path
278-
let write_start = Instant::now();
279-
std::fs::write(output_path, &codegen_result.code)?;
280-
trace!("[Compile #{compile_id}] Step 4/4: File write in {:?}", write_start.elapsed());
281-
282-
let elapsed = begin.elapsed();
283-
284-
{
285-
let mut outlook = self.outlook.lock().unwrap();
286-
outlook.count += 1;
287-
outlook.elapsed += elapsed;
288-
}
289-
290-
info!(
291-
"[Compile #{compile_id}] COMPLETE: {} -> {} in {:?}",
292-
file_path,
293-
output_path.display(),
294-
elapsed
295-
);
296-
297-
Ok(output_path.to_string_lossy().to_string())
182+
let compile_id = COMPILE_ID.fetch_add(1, Ordering::SeqCst);
183+
let begin = Instant::now();
184+
185+
info!(
186+
"[Compile #{compile_id}] START compile_file_to: {} -> {}",
187+
file_path,
188+
output_path.display()
189+
);
190+
trace!(
191+
"[Compile #{compile_id}] Input size: {} bytes, use_define_for_class_fields={}",
192+
input.len(),
193+
use_define_for_class_fields
194+
);
195+
196+
// CRITICAL FIX: Wrap entire compilation in its own scope to ensure
197+
// the allocator is dropped before the next file is processed.
198+
// This prevents OXC internal state corruption when processing
199+
// multiple files sequentially.
200+
let codegen_result = {
201+
// Parse the TypeScript source
202+
info!("[Compile #{compile_id}] Step 1/4: Parsing {}", file_path);
203+
let parse_start = Instant::now();
204+
let parser_config = self.get_parser_config();
205+
let mut parse_result = Parser::parse(&input, file_path, &parser_config)
206+
.map_err(|errors| anyhow::anyhow!("Parse errors: {:?}", errors))?;
207+
info!(
208+
"[Compile #{compile_id}] Step 1/4 complete: Parse in {:?}",
209+
parse_start.elapsed()
210+
);
211+
212+
debug!(
213+
"[Compile #{compile_id}] Memory addresses: allocator={:p}, program={:p}",
214+
&parse_result.allocator, &parse_result.program
215+
);
216+
trace!(
217+
"[Compile #{compile_id}] AST body slice: ptr={:p}, len={}",
218+
parse_result.program.body.as_ptr(),
219+
parse_result.program.body.len()
220+
);
221+
222+
// Transform the AST - borrow program mutably, don't move it out
223+
info!("[Compile #{compile_id}] Step 2/4: Transforming");
224+
let transform_start = Instant::now();
225+
let mut transformer_config = self.get_transformer_config();
226+
transformer_config.use_define_for_class_fields = use_define_for_class_fields;
227+
228+
// SAFETY: We borrow program with 'static lifetime from parse_result.
229+
// This is safe because:
230+
// 1. parse_result stays in scope for the entire inner block
231+
// 2. The program and allocator are dropped together when parse_result is
232+
// dropped
233+
// 3. We never use program after parse_result is dropped
234+
let program = unsafe {
235+
std::mem::transmute::<&mut oxc_ast::ast::Program<'static>, &mut oxc_ast::ast::Program<'_>>(
236+
&mut parse_result.program,
237+
)
238+
};
239+
240+
let source_type = oxc_span::SourceType::from_path(file_path).unwrap_or(oxc_span::SourceType::ts());
241+
242+
Transformer::transform(&parse_result.allocator, program, file_path, source_type, &transformer_config)
243+
.map_err(|errors| anyhow::anyhow!("Transform errors: {:?}", errors))?;
244+
info!(
245+
"[Compile #{compile_id}] Step 2/4 complete: Transform in {:?}",
246+
transform_start.elapsed()
247+
);
248+
trace!(
249+
"[Compile #{compile_id}] Program after transform - body ptr: {:p}",
250+
program.body.as_ptr()
251+
);
252+
253+
// Generate code - parse_result still alive
254+
info!("[Compile #{compile_id}] Step 3/4: Codegen");
255+
let codegen_start = Instant::now();
256+
let codegen_config = self.get_codegen_config();
257+
let codegen_result = Codegen::codegen(&parse_result.allocator, program, source_type, &codegen_config)
258+
.map_err(|e| anyhow::anyhow!("Codegen error: {}", e))?;
259+
info!(
260+
"[Compile #{compile_id}] Step 3/4 complete: Codegen in {:?}, output={}(bytes)",
261+
codegen_start.elapsed(),
262+
codegen_result.code.len()
263+
);
264+
265+
// Force drop of parse_result to ensure allocator is freed
266+
// before returning from this scope
267+
let _ = program;
268+
// parse_result will be dropped at end of scope
269+
codegen_result
270+
}; // parse_result and allocator dropped here - critical for preventing segfault
271+
272+
// Create parent directories if they don't exist
273+
if let Some(parent) = output_path.parent() {
274+
std::fs::create_dir_all(parent)?;
275+
}
276+
277+
// Write to the specified output path
278+
let write_start = Instant::now();
279+
std::fs::write(output_path, &codegen_result.code)?;
280+
trace!("[Compile #{compile_id}] Step 4/4: File write in {:?}", write_start.elapsed());
281+
282+
let elapsed = begin.elapsed();
283+
284+
{
285+
let mut outlook = self.outlook.lock().unwrap();
286+
outlook.count += 1;
287+
outlook.elapsed += elapsed;
288+
}
289+
290+
info!(
291+
"[Compile #{compile_id}] COMPLETE: {} -> {} in {:?}",
292+
file_path,
293+
output_path.display(),
294+
elapsed
295+
);
296+
297+
Ok(output_path.to_string_lossy().to_string())
298298
}
299299

300300
/// Get parser configuration from compiler config

Source/Fn/OXC/Transformer.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,15 @@ use oxc_allocator::Allocator;
1717
use oxc_ast::ast::Program;
1818
use oxc_semantic::SemanticBuilder;
1919
use oxc_span::SourceType;
20-
use oxc_transformer::{CompilerAssumptions, EnvOptions, JsxOptions, JsxRuntime, TransformOptions, Transformer, TypeScriptOptions};
20+
use oxc_transformer::{
21+
CompilerAssumptions,
22+
EnvOptions,
23+
JsxOptions,
24+
JsxRuntime,
25+
TransformOptions,
26+
Transformer,
27+
TypeScriptOptions,
28+
};
2129
use tracing::{debug, info, trace, warn};
2230

2331
/// Transformer configuration options
@@ -140,7 +148,7 @@ pub fn transform<'a>(
140148
let mut typescript_options = TypeScriptOptions::default();
141149
typescript_options.only_remove_type_imports = true;
142150
trace!("[Transform #{transform_id}] TypeScript options configured (only_remove_type_imports=true)");
143-
151+
144152
// Configure JSX transformation if enabled
145153
let jsx_options = if config.jsx {
146154
JsxOptions { runtime:JsxRuntime::Automatic, ..JsxOptions::default() }
@@ -149,7 +157,7 @@ pub fn transform<'a>(
149157
JsxOptions { runtime:JsxRuntime::Classic, ..JsxOptions::default() }
150158
};
151159
trace!("[Transform #{transform_id}] JSX options configured");
152-
160+
153161
// Configure environment options based on target
154162
let env_options_start = std::time::Instant::now();
155163
let env_options = EnvOptions::from_target(&config.target).unwrap_or_default();
@@ -158,15 +166,18 @@ pub fn transform<'a>(
158166
config.target,
159167
env_options_start.elapsed()
160168
);
161-
169+
162170
// Configure compiler assumptions for VSCode compatibility.
163171
// The `use_define_for_class_fields` flag from TypeScript:
164172
// - false => loose mode (direct assignment) => set_public_class_fields = true
165173
// - true => strict mode (defineProperty) => set_public_class_fields = false
166174
let mut assumptions = CompilerAssumptions::default();
167175
assumptions.set_public_class_fields = !config.use_define_for_class_fields;
168-
trace!("[Transform #{transform_id}] Compiler assumptions configured (set_public_class_fields={})", assumptions.set_public_class_fields);
169-
176+
trace!(
177+
"[Transform #{transform_id}] Compiler assumptions configured (set_public_class_fields={})",
178+
assumptions.set_public_class_fields
179+
);
180+
170181
// Create transform options with all VSCode compatibility settings
171182
let transform_options = TransformOptions {
172183
typescript:typescript_options,

Source/Fn/mod.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,3 @@ pub mod Transform;
99
pub mod NLS;
1010
pub mod Worker;
1111
pub mod Bundle;
12-
13-
// Re-export compiler for testing
14-
pub use OXC::Compiler;

0 commit comments

Comments
 (0)