windjammer 0.48.0

A simple language inspired by Go, Ruby, and Elixir that transpiles to Rust - 80% of Rust's power with 20% of the complexity
Documentation
//! JavaScript code generation backend (ES2020+)
//!
//! This module generates modern JavaScript with:
//! - ES2020+ features (async/await, optional chaining, etc.)
//! - Source maps for debugging
//! - TypeScript definitions (.d.ts)
//! - npm package.json

pub mod code_splitter;
pub mod differential_loading;
mod expression_generation;
mod generator;
pub mod minifier;
pub mod module_federation;
pub mod polyfills;
pub mod source_maps;
mod statement_generation;
pub mod tree_shaker;
mod type_conversion;
mod type_definitions;
pub mod v8_optimizer;
pub mod web_workers;

use crate::codegen::backend::{CodegenBackend, CodegenConfig, CodegenOutput, Target};
use crate::parser::Program;
use anyhow::Result;
use generator::JavaScriptGenerator;

/// JavaScript code generation backend
pub struct JavaScriptBackend {
    // JavaScript-specific state
}

impl JavaScriptBackend {
    pub fn new() -> Self {
        Self {}
    }
}

impl Default for JavaScriptBackend {
    fn default() -> Self {
        Self::new()
    }
}

impl CodegenBackend for JavaScriptBackend {
    fn name(&self) -> &str {
        "JavaScript"
    }

    fn target(&self) -> Target {
        Target::JavaScript
    }

    fn generate(&self, program: &Program, config: &CodegenConfig) -> Result<CodegenOutput> {
        // Apply tree shaking if configured
        let program = if config.tree_shake {
            tree_shaker::shake_tree(program)
        } else {
            program.clone()
        };

        let mut generator = JavaScriptGenerator::new();
        let mut code = generator.generate(&program);

        // Apply polyfills if configured
        if config.polyfills {
            let polyfill_config = polyfills::PolyfillConfig {
                target: polyfills::PolyfillTarget::ES2015,
                include_promise: true,
                include_array_methods: true,
                include_object_methods: true,
                include_symbol: false,
            };
            let polyfill_code = polyfills::generate_polyfills(&polyfill_config);
            code = format!("{}\n{}", polyfill_code, code);
        }

        // Apply V8 optimizations if configured
        if config.v8_optimize {
            let optimizer = v8_optimizer::V8Optimizer::new();
            code = optimizer.optimize(&code);
        }

        // Apply minification if configured
        if config.minify {
            let mut minifier = minifier::Minifier::new();
            code = minifier.minify(&code);
        }

        // Generate source maps if configured (before moving code)
        let source_map_json = if config.source_maps {
            let source_map = source_maps::generate_source_map("output.js", "input.wj", "", &code);
            Some(serde_json::to_string(&source_map).unwrap_or_default())
        } else {
            None
        };

        let mut output = CodegenOutput::new(code, "js".to_string());

        if let Some(source_map) = source_map_json {
            output = output.with_source_map(source_map);
        }

        // Generate TypeScript definitions if configured
        if config.type_definitions {
            if let Some(type_defs) = type_definitions::generate_type_definitions(&program) {
                output = output.with_type_definitions(type_defs);
            }
        }

        Ok(output)
    }

    fn make_idiomatic(&self, code: String, _config: &CodegenConfig) -> Result<String> {
        // TODO: Apply Prettier-like formatting
        // TODO: Convert to idiomatic JavaScript patterns
        Ok(code)
    }

    fn generate_type_definitions(&self, program: &Program) -> Option<String> {
        type_definitions::generate_type_definitions(program)
    }

    fn generate_additional_files(
        &self,
        _program: &Program,
        _config: &CodegenConfig,
    ) -> Vec<(String, String)> {
        vec![
            ("package.json".to_string(), self.generate_package_json()),
            (".gitignore".to_string(), self.generate_gitignore()),
        ]
    }

    fn target_specific_optimizations(&self) -> Vec<String> {
        vec![
            "async_await_optimization".to_string(),
            "closure_optimization".to_string(),
            "tree_shaking".to_string(),
        ]
    }
}

impl JavaScriptBackend {
    fn generate_package_json(&self) -> String {
        r#"{
  "name": "windjammer-generated",
  "version": "0.1.0",
  "description": "Generated by Windjammer JavaScript transpiler",
  "type": "module",
  "main": "index.js",
  "exports": {
    ".": "./index.js"
  },
  "engines": {
    "node": ">=18.0.0"
  },
  "keywords": ["windjammer"],
  "license": "MIT"
}
"#
        .to_string()
    }

    fn generate_gitignore(&self) -> String {
        r#"node_modules/
dist/
*.log
.DS_Store
"#
        .to_string()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_javascript_backend_creation() {
        let backend = JavaScriptBackend::new();
        assert_eq!(backend.name(), "JavaScript");
        assert_eq!(backend.target(), Target::JavaScript);
    }

    #[test]
    fn test_generates_package_json() {
        let backend = JavaScriptBackend::new();
        let files = backend
            .generate_additional_files(&Program { items: vec![] }, &CodegenConfig::default());
        assert!(!files.is_empty());
        assert!(files.iter().any(|(name, _)| name == "package.json"));
    }

    #[test]
    fn test_generates_code() {
        let backend = JavaScriptBackend::new();
        let program = Program { items: vec![] };
        let config = CodegenConfig::default();
        let result = backend.generate(&program, &config);
        assert!(result.is_ok());
    }
}