NativePlugin

Struct NativePlugin 

Source
pub struct NativePlugin { /* private fields */ }
Expand description

The main plugin class for macro expansion with caching support.

NativePlugin is designed to be instantiated once and reused across multiple file processing operations. It maintains a cache of expansion results keyed by filepath and version, enabling efficient incremental processing.

§Thread Safety

The plugin is thread-safe through the use of Mutex for internal state. However, macro expansion itself runs in a separate thread with a 32MB stack to prevent stack overflow during deep AST recursion.

§Example

// Create a single plugin instance (typically at startup)
const plugin = new NativePlugin();

// Process files with caching
const result1 = plugin.process_file("src/foo.ts", code1, { version: "1" });
const result2 = plugin.process_file("src/foo.ts", code2, { version: "1" }); // Cache hit!
const result3 = plugin.process_file("src/foo.ts", code3, { version: "2" }); // Cache miss

// Get a mapper for position translation
const mapper = plugin.get_mapper("src/foo.ts");

Implementations§

Source§

impl NativePlugin

Source

pub fn new() -> Self

Creates a new NativePlugin instance.

Initializes the plugin with an empty cache and sets up a default log file at /tmp/macroforge-plugin.log for debugging purposes.

§Returns

A new NativePlugin ready for processing files.

§Side Effects

Creates or clears the log file at /tmp/macroforge-plugin.log.

Source

pub fn log(&self, message: String)

Writes a message to the plugin’s log file.

Useful for debugging macro expansion issues in production environments.

§Arguments
  • message - The message to log
§Note

Messages are appended to the log file. If the log file hasn’t been configured or cannot be written to, the message is silently dropped.

Source

pub fn set_log_file(&self, path: String)

Sets the path for the plugin’s log file.

§Arguments
  • path - The file path to use for logging
§Note

This does not create the file; it will be created when the first message is logged.

Source

pub fn process_file( &self, _env: Env, filepath: String, code: String, options: Option<ProcessFileOptions>, ) -> Result<ExpandResult>

Processes a TypeScript file through the macro expansion system.

This is the main entry point for file processing. It handles caching, thread isolation (to prevent stack overflow), and error recovery.

§Arguments
  • _env - NAPI environment (unused but required by NAPI)
  • filepath - Path to the file (used for TSX detection and caching)
  • code - The TypeScript source code to process
  • options - Optional configuration for expansion and caching
§Returns

An ExpandResult containing the expanded code, diagnostics, and source mapping.

§Errors

Returns an error if:

  • Thread spawning fails
  • The worker thread panics (often due to stack overflow)
  • Macro expansion fails internally
§Performance
  • Uses a 32MB thread stack to prevent stack overflow during deep AST recursion
  • Caches results by filepath and version for efficient incremental processing
  • Early bailout for files without @derive decorators
§Thread Safety

Macro expansion runs in a separate thread because:

  1. SWC AST operations can be deeply recursive, exceeding default stack limits
  2. Node.js thread stack is typically only 2MB
  3. Panics in the worker thread are caught and reported gracefully
Source

pub fn get_mapper(&self, filepath: String) -> Option<NativeMapper>

Retrieves a position mapper for a previously processed file.

The mapper enables translation between original and expanded source positions, which is essential for IDE features like error reporting and navigation.

§Arguments
  • filepath - Path to the file (must have been previously processed)
§Returns

Some(NativeMapper) if the file has been processed and has source mapping data, None if the file hasn’t been processed or has no mapping (no macros expanded).

Source

pub fn map_diagnostics( &self, filepath: String, diags: Vec<JsDiagnostic>, ) -> Vec<JsDiagnostic>

Maps diagnostics from expanded source positions back to original source positions.

This is used by IDE integrations to show errors at the correct locations in the user’s original code, rather than in the macro-expanded output.

§Arguments
  • filepath - Path to the file the diagnostics are for
  • diags - Diagnostics with positions in the expanded source
§Returns

Diagnostics with positions mapped back to the original source. If no mapper is available for the file, returns diagnostics unchanged.

Trait Implementations§

Source§

impl Default for NativePlugin

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl FromNapiMutRef for NativePlugin

Source§

unsafe fn from_napi_mut_ref( env: napi_env, napi_val: napi_value, ) -> Result<&'static mut Self>

Safety Read more
Source§

impl FromNapiRef for NativePlugin

Source§

unsafe fn from_napi_ref( env: napi_env, napi_val: napi_value, ) -> Result<&'static Self>

Safety Read more
Source§

impl JavaScriptClassExt for NativePlugin

Source§

fn into_instance<'scope>( self, env: &'scope Env, ) -> Result<ClassInstance<'scope, Self>>

Source§

fn into_reference(self, env: Env) -> Result<Reference<Self>>

Source§

fn instance_of<'env, V: JsValue<'env>>(env: &Env, value: &V) -> Result<bool>

Source§

impl ObjectFinalize for NativePlugin

Source§

fn finalize(self, env: Env) -> Result<(), Error>

Source§

impl ToNapiValue for NativePlugin

Source§

impl TypeName for &NativePlugin

Source§

impl TypeName for &mut NativePlugin

Source§

impl TypeName for NativePlugin

Source§

impl ValidateNapiValue for &NativePlugin

Source§

unsafe fn validate(env: napi_env, napi_val: napi_value) -> Result<napi_value>

Safety Read more
Source§

impl ValidateNapiValue for &mut NativePlugin

Source§

unsafe fn validate(env: napi_env, napi_val: napi_value) -> Result<napi_value>

Safety Read more

Auto Trait Implementations§

Blanket Implementations§

§

impl<T> Any for T
where T: 'static + ?Sized,

§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> Borrow<T> for T
where T: ?Sized,

§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
§

impl<T> BorrowMut<T> for T
where T: ?Sized,

§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> From<T> for T

§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
§

impl<T, U> Into<U> for T
where U: From<T>,

§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> JsValuesTupleIntoVec for T
where T: ToNapiValue,

§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> Send for T
where T: ?Sized,

Source§

impl<T> Sync for T
where T: ?Sized,