From 63c72d689a73b2b0ed5db5abeeceaf598e73c464 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 13 Jul 2024 23:16:06 +0800 Subject: [PATCH] chore: align transform logic (#8) --- packages/core/index.d.ts | 4 +- packages/core/index.js | 1 + packages/core/oxc-node.wasi-browser.js | 15 ++-- packages/core/oxc-node.wasi.cjs | 15 ++-- src/lib.rs | 108 +++++++++++++++---------- 5 files changed, 87 insertions(+), 56 deletions(-) diff --git a/packages/core/index.d.ts b/packages/core/index.d.ts index c6817a8..b1ebf35 100644 --- a/packages/core/index.d.ts +++ b/packages/core/index.d.ts @@ -49,5 +49,7 @@ export interface ResolveFnOutput { importAttributes?: Record | null } -export declare function transform(path: string, code: string | Uint8Array): Output +export declare function transform(path: string, source: string | Uint8Array): Output + +export declare function transformAsync(path: string, source: string | Uint8Array | Buffer): Promise diff --git a/packages/core/index.js b/packages/core/index.js index 8bd36e0..60c13c2 100644 --- a/packages/core/index.js +++ b/packages/core/index.js @@ -366,3 +366,4 @@ module.exports.initTracing = nativeBinding.initTracing module.exports.load = nativeBinding.load module.exports.resolve = nativeBinding.resolve module.exports.transform = nativeBinding.transform +module.exports.transformAsync = nativeBinding.transformAsync diff --git a/packages/core/oxc-node.wasi-browser.js b/packages/core/oxc-node.wasi-browser.js index ff5da8d..cae402d 100644 --- a/packages/core/oxc-node.wasi-browser.js +++ b/packages/core/oxc-node.wasi-browser.js @@ -55,15 +55,18 @@ function __napi_rs_initialize_modules(__napiInstance) { __napiInstance.exports['__napi_register__Output_struct_1']?.() __napiInstance.exports['__napi_register__Output_impl_4']?.() __napiInstance.exports['__napi_register__transform_5']?.() - __napiInstance.exports['__napi_register__ResolveContext_struct_6']?.() - __napiInstance.exports['__napi_register__ResolveFnOutput_struct_7']?.() - __napiInstance.exports['__napi_register__resolve_8']?.() - __napiInstance.exports['__napi_register__LoadContext_struct_9']?.() - __napiInstance.exports['__napi_register__LoadFnOutput_struct_10']?.() - __napiInstance.exports['__napi_register__load_11']?.() + __napiInstance.exports['__napi_register__TransformTask_impl_6']?.() + __napiInstance.exports['__napi_register__transform_async_7']?.() + __napiInstance.exports['__napi_register__ResolveContext_struct_8']?.() + __napiInstance.exports['__napi_register__ResolveFnOutput_struct_9']?.() + __napiInstance.exports['__napi_register__resolve_10']?.() + __napiInstance.exports['__napi_register__LoadContext_struct_11']?.() + __napiInstance.exports['__napi_register__LoadFnOutput_struct_12']?.() + __napiInstance.exports['__napi_register__load_13']?.() } export const Output = __napiModule.exports.Output export const initTracing = __napiModule.exports.initTracing export const load = __napiModule.exports.load export const resolve = __napiModule.exports.resolve export const transform = __napiModule.exports.transform +export const transformAsync = __napiModule.exports.transformAsync diff --git a/packages/core/oxc-node.wasi.cjs b/packages/core/oxc-node.wasi.cjs index 4c07f40..8b74a1d 100644 --- a/packages/core/oxc-node.wasi.cjs +++ b/packages/core/oxc-node.wasi.cjs @@ -86,15 +86,18 @@ function __napi_rs_initialize_modules(__napiInstance) { __napiInstance.exports['__napi_register__Output_struct_1']?.() __napiInstance.exports['__napi_register__Output_impl_4']?.() __napiInstance.exports['__napi_register__transform_5']?.() - __napiInstance.exports['__napi_register__ResolveContext_struct_6']?.() - __napiInstance.exports['__napi_register__ResolveFnOutput_struct_7']?.() - __napiInstance.exports['__napi_register__resolve_8']?.() - __napiInstance.exports['__napi_register__LoadContext_struct_9']?.() - __napiInstance.exports['__napi_register__LoadFnOutput_struct_10']?.() - __napiInstance.exports['__napi_register__load_11']?.() + __napiInstance.exports['__napi_register__TransformTask_impl_6']?.() + __napiInstance.exports['__napi_register__transform_async_7']?.() + __napiInstance.exports['__napi_register__ResolveContext_struct_8']?.() + __napiInstance.exports['__napi_register__ResolveFnOutput_struct_9']?.() + __napiInstance.exports['__napi_register__resolve_10']?.() + __napiInstance.exports['__napi_register__LoadContext_struct_11']?.() + __napiInstance.exports['__napi_register__LoadFnOutput_struct_12']?.() + __napiInstance.exports['__napi_register__load_13']?.() } module.exports.Output = __napiModule.exports.Output module.exports.initTracing = __napiModule.exports.initTracing module.exports.load = __napiModule.exports.load module.exports.resolve = __napiModule.exports.resolve module.exports.transform = __napiModule.exports.transform +module.exports.transformAsync = __napiModule.exports.transformAsync diff --git a/src/lib.rs b/src/lib.rs index 459d84b..05d9bd9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ use std::{ borrow::Cow, collections::HashMap, - env, + env, mem, path::{Path, PathBuf}, sync::OnceLock, }; @@ -160,9 +160,46 @@ impl Output { } #[napi] -pub fn transform(path: String, code: Either) -> Result { - let allocator = Allocator::default(); +pub fn transform(path: String, source: Either) -> Result { let src_path = Path::new(&path); + oxc_transform(src_path, &source) +} + +pub struct TransformTask { + path: String, + source: Either3, +} + +#[napi] +impl Task for TransformTask { + type Output = Output; + type JsValue = Output; + + fn compute(&mut self) -> Result { + let src_path = Path::new(&self.path); + oxc_transform(src_path, &self.source) + } + + fn resolve(&mut self, _: Env, output: Self::Output) -> Result { + Ok(output) + } + + fn finally(&mut self, _: Env) -> Result<()> { + mem::drop(mem::replace(&mut self.source, Either3::A(String::new()))); + Ok(()) + } +} + +#[napi] +pub fn transform_async( + path: String, + source: Either3, +) -> AsyncTask { + AsyncTask::new(TransformTask { path, source }) +} + +fn oxc_transform(src_path: &Path, code: &S) -> Result { + let allocator = Allocator::default(); let source_type = SourceType::from_path(src_path).unwrap_or_default(); let source_str = code.try_as_str()?; let ParserReturn { @@ -428,14 +465,14 @@ pub fn load( let loaded = next_load.call((url.clone(), Some(context)))?; match loaded { - Either::A(output) => Ok(Either::A(oxc_transform(url, output)?)), + Either::A(output) => Ok(Either::A(transform_output(url, output)?)), Either::B(mut promise) => promise - .then(move |ctx| oxc_transform(url, ctx.value)) + .then(move |ctx| transform_output(url, ctx.value)) .map(Either::B), } } -fn oxc_transform(url: String, output: LoadFnOutput) -> Result { +fn transform_output(url: String, output: LoadFnOutput) -> Result { match &output.source { Some(Either4::D(_)) | None => { tracing::debug!("No source code to transform {}", url); @@ -446,8 +483,6 @@ fn oxc_transform(url: String, output: LoadFnOutput) -> Result { }) } Some(Either4::A(_) | Either4::B(_) | Either4::C(_)) => { - let source = output.source.as_ref().unwrap().try_as_str()?; - let allocator = Allocator::default(); let src_path = Path::new(&url); let ext = src_path.extension().and_then(|ext| ext.to_str()); let jsx = ext @@ -471,46 +506,13 @@ fn oxc_transform(url: String, output: LoadFnOutput) -> Result { } }; tracing::debug!(url = ?url, jsx = ?jsx, src_path = ?src_path, source_type = ?source_type, "running oxc transform"); - let ParserReturn { - trivias, - mut program, - errors, - .. - } = Parser::new(&allocator, source, source_type).parse(); - if !errors.is_empty() { - for error in &errors { - eprintln!("{}", error); - } - return Err(Error::new( - Status::GenericFailure, - format!("Failed to parse source file {}", url), - )); - } - let TransformerReturn { errors, .. } = Transformer::new( - &allocator, - src_path, - source_type, - source, - trivias, - Default::default(), - ) - .build(&mut program); - - if !errors.is_empty() { - for error in &errors { - eprintln!("{}", error); - } - return Err(Error::new( - Status::GenericFailure, - "Failed to transform source file", - )); - } + let transform_output = oxc_transform(src_path, output.source.as_ref().unwrap())?; tracing::debug!("loaded {} format: {}", url, output.format); Ok(LoadFnOutput { format: output.format, source: Some(Either4::B(Uint8Array::from_string( - CodeGenerator::new().build(&program).source_text, + transform_output.0.source_text, ))), response_url: Some(url), }) @@ -536,6 +538,26 @@ impl TryAsStr for Either { } } +impl TryAsStr for Either3 { + fn try_as_str(&self) -> Result<&str> { + match self { + Either3::A(s) => Ok(s), + Either3::B(arr) => std::str::from_utf8(arr).map_err(|_| { + Error::new( + Status::GenericFailure, + "Failed to convert Uint8Array to Vec", + ) + }), + Either3::C(buf) => std::str::from_utf8(buf).map_err(|_| { + Error::new( + Status::GenericFailure, + "Failed to convert Buffer to Vec", + ) + }), + } + } +} + impl TryAsStr for Either4 { fn try_as_str(&self) -> Result<&str> { match self {