Rust ECMAScript 2021兼容库swc_ecma_compat_es2021的使用,实现现代JavaScript语法转译与兼容性处理

Rust ECMAScript 2021兼容库swc_ecma_compat_es2021的使用,实现现代JavaScript语法转译与兼容性处理

安装

在项目目录中运行以下Cargo命令:

cargo add swc_ecma_compat_es2021

或者在Cargo.toml中添加以下行:

swc_ecma_compat_es2021 = "24.0.0"

基本使用示例

以下是一个使用swc_ecma_compat_es2021库转译ECMAScript 2021代码的完整示例:

use swc_common::{
    errors::{ColorConfig, Handler},
    sync::Lrc,
    SourceMap,
};
use swc_ecma_compat_es2021::es2021;
use swc_ecma_parser::{lexer::Lexer, Parser, StringInput, Syntax, TsConfig};
use swc_ecma_transforms_base::resolver;
use swc_ecma_visit::FoldWith;

fn main() {
    // 创建源代码映射和错误处理器
    let cm: Lrc<SourceMap> = Default::default();
    let handler = Handler::with_tty_emitter(
        ColorConfig::Auto,
        true,
        false,
        Some(cm.clone()),
    );

    // 要转译的源代码 - 包含ECMAScript 2021特性
    let code = r#"
        // 逻辑赋值运算符
        let x = 1;
        x ||= 2;
        
        // 数字分隔符
        const billion = 1_000_000_000;
        
        // Promise.any
        Promise.any([
            fetch('https://example.com'),
            fetch('https://example.org')
        ]).then((response) => {
            console.log(response);
        });
        
        // String.prototype.replaceAll
        const str = 'hello world';
        str.replaceAll('hello', 'hi');
    "#;

    // 创建词法分析器和解析器
    let fm = cm.new_source_file(
        swc_common::FileName::Anon,
        code.to_string(),
    );
    let lexer = Lexer::new(
        Syntax::Es(Default::default()),
        Default::default(),
        StringInput::from(&*fm),
        None,
    );
    let mut parser = Parser::new_from(lexer);

    // 解析代码为AST
    let module = match parser.parse_module() {
        Ok(module) => module,
        Err(err) => {
            err.into_diagnostic(&handler).emit();
            return;
        }
    };

    // 应用作用域解析器
    let module = module.fold_with(&mut resolver());

    // 应用ECMAScript 2021转译
    let module = module.fold_with(&mut es2021());

    // 打印转译后的代码
    let output = swc_ecma_codegen::Emitter {
        cfg: Default::default(),
        cm: cm.clone(),
        comments: None,
        wr: Box::new(swc_ecma_codegen::text_writer::JsWriter::new(
            cm.clone(),
            "\n",
            Box::new(std::io::stdout()),
            None,
        )),
    };
    output.emit_module(&module).unwrap();
}

功能说明

swc_ecma_compat_es2021库提供了对ECMAScript 2021特性的转译支持,包括但不限于:

  1. 逻辑赋值运算符 (||=, &&=, ??=)
  2. 数字分隔符 (1_000_000)
  3. Promise.anyAggregateError
  4. String.prototype.replaceAll
  5. WeakRefs 和 FinalizationRegistry

高级配置示例

use swc_ecma_compat_es2021::Config;
use swc_ecma_visit::FoldWith;

// 自定义配置
let config = Config {
    logical_assign: true,    // 转译逻辑赋值运算符
    numeric_separator: true, // 转译数字分隔符
    promise_any: true,       // 转译Promise.any
    replace_all: true,       // 转译String.prototype.replaceAll
    weak_ref: true,          // 转译WeakRef和FinalizationRegistry
};

// 应用自定义配置的转译器
let module = module.fold_with(&mut es2021(config));

注意事项

  1. 该库是SWC生态系统的一部分,通常与其他SWC工具链一起使用
  2. 转译后的代码可能需要额外的polyfill来支持旧版JavaScript环境
  3. 版本24.0.0需要Rust 2021 edition

1 回复

Rust ECMAScript 2021兼容库swc_ecma_compat_es2021使用指南

概述

swc_ecma_compat_es2021是SWC(一个用Rust编写的高速JavaScript/TypeScript转译器)的一部分,专门用于将现代JavaScript(ECMAScript 2021)语法转换为向后兼容的JavaScript代码。这个库特别适合需要在旧版浏览器或环境中运行现代JavaScript代码的场景。

主要功能

  • 将ES2021语法转换为兼容性更好的ES5/ES6代码
  • 支持逻辑赋值运算符(&&=, ||=, ??=)
  • 支持数字分隔符(1_000_000)
  • 支持Promise.any和AggregateError
  • 支持String.prototype.replaceAll
  • 其他ES2021特性的转换

安装方法

在Cargo.toml中添加依赖:

[dependencies]
swc_ecma_compat_es2021 = "0.100"

基本使用方法

1. 简单转译示例

use swc_ecma_compat_es2021::es2021;
use swc_ecma_parser::{Syntax, EsConfig};
use swc_common::{SourceMap, FileName};

fn main() {
    let cm = SourceMap::default();
    let fm = cm.new_source_file(
        FileName::Anon,
        "let x = 1_000_000; x &&= 2_000_000;".to_string(),
    );
    
    let mut parser = swc_ecma_parser::Parser::new(
        Syntax::Es(EsConfig {
            ..Default::default()
        }),
        fm.as_ref(),
        None,
    );
    
    let module = parser.parse_module().unwrap();
    
    let transformed = es2021(cm.clone(), Default::default(), module);
    
    println!("{:?}", transformed);
}

2. 配置选项

use swc_ecma_compat_es2021::{es2021, Config};

let config = Config {
    // 配置特定转换选项
    ..Default::default()
};

let transformed = es2021(cm.clone(), config, module);

高级用法

处理Promise.any

// 输入代码
let code = r#"
async function fetchFirstSuccess(urls) {
    return await Promise.any(urls.map(url => fetch(url)));
}
"#;

// 经过swc_ecma_compat_es2021转换后,Promise.any会被转换为兼容性实现

处理逻辑赋值运算符

// 输入代码
let code = r#"
let x = null;
x ??= 42;  // 如果x为null或undefined,则赋值为42
"#;

// 转换后的代码会使用更兼容的语法实现相同逻辑

处理字符串replaceAll方法

// 输入代码
let code = r#"
const str = 'hello-world';
const newStr = str.replaceAll('-', '_');
"#;

// 转换后的代码会使用正则表达式或其他兼容方法实现replaceAll

完整示例demo

// 引入必要的模块
use swc_common::{SourceMap, FileName};
use swc_ecma_compat_es2021::{es2021, Config};
use swc_ecma_parser::{Syntax, EsConfig};
use swc_ecma_visit::FoldWith;

fn main() {
    // 1. 创建源代码映射
    let cm = SourceMap::default();
    
    // 2. 创建包含ES2021特性的源代码文件
    let fm = cm.new_source_file(
        FileName::Anon,
        r#"
        // ES2021特性示例
        const budget = 1_000_000;  // 数字分隔符
        let user = { name: 'John' };
        
        // 逻辑赋值运算符
        user.name ??= 'Anonymous';
        
        // String.replaceAll
        const text = 'hello-world';
        const newText = text.replaceAll('-', '_');
        
        // Promise.any
        async function loadFirstAvailable(urls) {
            return await Promise.any(urls.map(url => fetch(url)));
        }
        "#.to_string(),
    );
    
    // 3. 创建ES语法解析器
    let mut parser = swc_ecma_parser::Parser::new(
        Syntax::Es(EsConfig {
            num_sep: true,  // 启用数字分隔符解析
            ..Default::default()
        }),
        fm.as_ref(),
        None,
    );
    
    // 4. 解析模块
    let module = parser.parse_module().unwrap();
    
    // 5. 配置转换选项
    let config = Config {
        // 这里可以配置特定转换选项
        ..Default::default()
    };
    
    // 6. 执行ES2021兼容转换
    let transformed = module.fold_with(&mut es2021(cm.clone(), config));
    
    // 7. 打印转换结果
    println!("转换后的代码:\n{:?}", transformed);
}

实际应用场景

  1. 构建工具集成:将swc_ecma_compat_es2021集成到你的构建流程中,确保生成的代码能在更多环境中运行

  2. 库开发:开发JavaScript库时,使用现代语法编写,然后转译为兼容性更好的代码发布

  3. 旧项目升级:在维护旧项目时,允许使用新语法编写代码,然后转译为项目支持的ECMAScript版本

性能考虑

由于SWC是用Rust编写的,swc_ecma_compat_es2021在性能上比基于JavaScript的转译器(如Babel)有显著优势,特别适合大型项目或需要频繁转译的场景。

注意事项

  1. 某些ES2021特性可能需要polyfill才能在旧环境中完全工作
  2. 转译后的代码可能会比原始代码更冗长
  3. 对于完全支持ES2021的环境,不需要使用此转译器

通过合理使用swc_ecma_compat_es2021,开发者可以享受现代JavaScript语法带来的便利,同时确保代码在各种环境中的兼容性。

回到顶部