Skip to content

Commit

Permalink
feat(napi/transform): return helpers information
Browse files Browse the repository at this point in the history
closes #7599
  • Loading branch information
Boshen committed Dec 9, 2024
1 parent c254a5b commit d672bd7
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 15 deletions.
33 changes: 21 additions & 12 deletions crates/oxc_transformer/src/common/helper_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ pub enum Helper {
}

impl Helper {
const fn name(self) -> &'static str {
pub const fn name(self) -> &'static str {
match self {
Self::AwaitAsyncGenerator => "awaitAsyncGenerator",
Self::AsyncGeneratorDelegate => "asyncGeneratorDelegate",
Expand Down Expand Up @@ -184,6 +184,7 @@ pub struct HelperLoaderStore<'a> {
mode: HelperLoaderMode,
/// Loaded helpers, determined what helpers are loaded and what imports should be added.
loaded_helpers: RefCell<FxHashMap<Helper, BoundIdentifier<'a>>>,
pub(crate) used_helpers: RefCell<FxHashMap<Helper, String>>,
}

impl<'a> HelperLoaderStore<'a> {
Expand All @@ -192,6 +193,7 @@ impl<'a> HelperLoaderStore<'a> {
module_name: options.module_name.clone(),
mode: options.mode,
loaded_helpers: RefCell::new(FxHashMap::default()),
used_helpers: RefCell::new(FxHashMap::default()),
}
}
}
Expand Down Expand Up @@ -238,9 +240,12 @@ impl<'a> TransformCtx<'a> {
/// Load a helper function and return a callee expression.
pub fn helper_load(&self, helper: Helper, ctx: &mut TraverseCtx<'a>) -> Expression<'a> {
let helper_loader = &self.helper_loader;
let source = helper_loader.get_runtime_source(helper, ctx);
helper_loader.used_helpers.borrow_mut().entry(helper).or_insert_with(|| source.to_string());

match helper_loader.mode {
HelperLoaderMode::Runtime => {
helper_loader.transform_for_runtime_helper(helper, self, ctx)
helper_loader.transform_for_runtime_helper(helper, source, self, ctx)
}
HelperLoaderMode::External => {
HelperLoaderStore::transform_for_external_helper(helper, ctx)
Expand All @@ -257,32 +262,25 @@ impl<'a> HelperLoaderStore<'a> {
fn transform_for_runtime_helper(
&self,
helper: Helper,
source: Atom<'a>,
transform_ctx: &TransformCtx<'a>,
ctx: &mut TraverseCtx<'a>,
) -> Expression<'a> {
let mut loaded_helpers = self.loaded_helpers.borrow_mut();
let binding = loaded_helpers
.entry(helper)
.or_insert_with(|| self.get_runtime_helper(helper, transform_ctx, ctx));
.or_insert_with(|| Self::get_runtime_helper(helper, source, transform_ctx, ctx));
binding.create_read_expression(ctx)
}

fn get_runtime_helper(
&self,
helper: Helper,
source: Atom<'a>,
transform_ctx: &TransformCtx<'a>,
ctx: &mut TraverseCtx<'a>,
) -> BoundIdentifier<'a> {
let helper_name = helper.name();

// Construct string directly in arena without an intermediate temp allocation
let len = self.module_name.len() + "/helpers/".len() + helper_name.len();
let mut source = ArenaString::with_capacity_in(len, ctx.ast.allocator);
source.push_str(&self.module_name);
source.push_str("/helpers/");
source.push_str(helper_name);
let source = Atom::from(source.into_bump_str());

let flag = if transform_ctx.source_type.is_module() {
SymbolFlags::Import
} else {
Expand All @@ -295,6 +293,17 @@ impl<'a> HelperLoaderStore<'a> {
binding
}

// Construct string directly in arena without an intermediate temp allocation
fn get_runtime_source(&self, helper: Helper, ctx: &mut TraverseCtx<'a>) -> Atom<'a> {
let helper_name = helper.name();
let len = self.module_name.len() + "/helpers/".len() + helper_name.len();
let mut source = ArenaString::with_capacity_in(len, ctx.ast.allocator);
source.push_str(&self.module_name);
source.push_str("/helpers/");
source.push_str(helper_name);
Atom::from(source.into_bump_str())
}

fn transform_for_external_helper(helper: Helper, ctx: &mut TraverseCtx<'a>) -> Expression<'a> {
static HELPER_VAR: &str = "babelHelpers";

Expand Down
11 changes: 9 additions & 2 deletions crates/oxc_transformer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,11 @@ use es2021::ES2021;
use es2022::ES2022;
use jsx::Jsx;
use regexp::RegExp;
use rustc_hash::FxHashMap;
use typescript::TypeScript;

pub use crate::{
common::helper_loader::{HelperLoaderMode, HelperLoaderOptions},
common::helper_loader::{Helper, HelperLoaderMode, HelperLoaderOptions},
compiler_assumptions::CompilerAssumptions,
es2015::{ArrowFunctionsOptions, ES2015Options},
jsx::{JsxOptions, JsxRuntime, ReactRefreshOptions},
Expand All @@ -63,10 +64,14 @@ pub use crate::{
typescript::{RewriteExtensionsMode, TypeScriptOptions},
};

#[non_exhaustive]
pub struct TransformerReturn {
pub errors: std::vec::Vec<OxcDiagnostic>,
pub symbols: SymbolTable,
pub scopes: ScopeTree,
/// Helpers used by this transform.
#[deprecated = "Internal usage only"]
pub helpers_used: FxHashMap<Helper, String>,
}

pub struct Transformer<'a> {
Expand Down Expand Up @@ -128,7 +133,9 @@ impl<'a> Transformer<'a> {
};

let (symbols, scopes) = traverse_mut(&mut transformer, allocator, program, symbols, scopes);
TransformerReturn { errors: self.ctx.take_errors(), symbols, scopes }
let helpers_used = self.ctx.helper_loader.used_helpers.borrow_mut().drain().collect();
#[allow(deprecated)]
TransformerReturn { errors: self.ctx.take_errors(), symbols, scopes, helpers_used }
}
}

Expand Down
12 changes: 12 additions & 0 deletions napi/transform/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,18 @@ export interface TransformResult {
* {@link TransformOptions#sourcemap sourcemap} are set to `true`.
*/
declarationMap?: SourceMap
/**
* Helpers used.
*
* @internal
*
* Example:
*
* ```text
* { "_objectSpread": "@babel/runtime/helpers/objectSpread2" }
* ```
*/
helpersUsed: Record<string, string>
/**
* Parse and transformation errors.
*
Expand Down
34 changes: 33 additions & 1 deletion napi/transform/src/transformer.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
// NOTE: Types must be aligned with [@types/babel__core](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/b5dc32740d9b45d11cff9b025896dd333c795b39/types/babel__core/index.d.ts).
#![allow(rustdoc::bare_urls)]

use std::path::{Path, PathBuf};
use std::{
ops::ControlFlow,
path::{Path, PathBuf},
};

use napi::Either;
use napi_derive::napi;
Expand Down Expand Up @@ -50,6 +53,18 @@ pub struct TransformResult {
/// {@link TransformOptions#sourcemap sourcemap} are set to `true`.
pub declaration_map: Option<SourceMap>,

/// Helpers used.
///
/// @internal
///
/// Example:
///
/// ```text
/// { "_objectSpread": "@babel/runtime/helpers/objectSpread2" }
/// ```
#[napi(ts_type = "Record<string, string>")]
pub helpers_used: FxHashMap<String, String>,

/// Parse and transformation errors.
///
/// Oxc's parser recovers from common syntax errors, meaning that
Expand Down Expand Up @@ -461,6 +476,7 @@ struct Compiler {
define: Option<ReplaceGlobalDefinesConfig>,
inject: Option<InjectGlobalVariablesConfig>,

helpers_used: FxHashMap<String, String>,
errors: Vec<OxcDiagnostic>,
}

Expand Down Expand Up @@ -527,6 +543,7 @@ impl Compiler {
declaration_map: None,
define,
inject,
helpers_used: FxHashMap::default(),
errors: vec![],
})
}
Expand Down Expand Up @@ -568,6 +585,20 @@ impl CompilerInterface for Compiler {
self.declaration.replace(ret.code);
self.declaration_map = ret.map.map(SourceMap::from);
}

#[allow(deprecated)]
fn after_transform(
&mut self,
_program: &mut oxc::ast::ast::Program<'_>,
transformer_return: &mut oxc::transformer::TransformerReturn,
) -> ControlFlow<()> {
self.helpers_used = transformer_return
.helpers_used
.drain()
.map(|(helper, source)| (helper.name().to_string(), source))
.collect();
ControlFlow::Continue(())
}
}

/// Transpile a JavaScript or TypeScript into a target ECMAScript version.
Expand Down Expand Up @@ -629,6 +660,7 @@ pub fn transform(
map: compiler.printed_sourcemap,
declaration: compiler.declaration,
declaration_map: compiler.declaration_map,
helpers_used: compiler.helpers_used,
errors: compiler.errors.into_iter().map(Error::from).collect(),
}
}
3 changes: 3 additions & 0 deletions napi/transform/test/transform.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ describe('helpers', () => {
helpers: { mode },
});
expect(ret.code).toEqual(expected);
expect(ret.helpersUsed).toStrictEqual({
objectSpread2: '@babel/runtime/helpers/objectSpread2',
});
});
});

Expand Down

0 comments on commit d672bd7

Please sign in to comment.