mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
feat(wasm): add wasm to oxc (#130)
This commit is contained in:
parent
500f42b134
commit
24d327c40d
8 changed files with 346 additions and 11 deletions
119
Cargo.lock
generated
119
Cargo.lock
generated
|
|
@ -100,6 +100,12 @@ version = "1.0.79"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
|
|
@ -183,7 +189,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "bff0805f79ecb1b35163f3957a6934ea8d04fcd36ef98b52e7316f63e72e73d1"
|
||||
dependencies = [
|
||||
"castaway",
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
|
|
@ -203,6 +209,16 @@ dependencies = [
|
|||
"windows-sys 0.42.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "console_error_panic_hook"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "convert_case"
|
||||
version = "0.6.0"
|
||||
|
|
@ -218,7 +234,7 @@ version = "1.3.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -261,7 +277,7 @@ version = "0.5.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
|
|
@ -271,7 +287,7 @@ version = "0.8.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
|
@ -283,7 +299,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"crossbeam-utils",
|
||||
"memoffset",
|
||||
"scopeguard",
|
||||
|
|
@ -295,7 +311,7 @@ version = "0.8.15"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -316,7 +332,7 @@ version = "0.8.32"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -380,7 +396,7 @@ version = "0.2.8"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
|
@ -613,7 +629,7 @@ version = "0.4.17"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -631,6 +647,12 @@ dependencies = [
|
|||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memory_units"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3"
|
||||
|
||||
[[package]]
|
||||
name = "miette"
|
||||
version = "5.5.0"
|
||||
|
|
@ -905,6 +927,25 @@ dependencies = [
|
|||
"oxc_ast",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oxc_wasm"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"miette",
|
||||
"oxc_allocator",
|
||||
"oxc_ast",
|
||||
"oxc_diagnostics",
|
||||
"oxc_linter",
|
||||
"oxc_parser",
|
||||
"oxc_semantic",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-test",
|
||||
"wee_alloc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.2.0"
|
||||
|
|
@ -1048,6 +1089,12 @@ dependencies = [
|
|||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scoped-tls"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
|
|
@ -1239,7 +1286,7 @@ version = "1.1.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
|
|
@ -1385,7 +1432,9 @@ version = "0.2.84"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
|
|
@ -1404,6 +1453,18 @@ dependencies = [
|
|||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.84"
|
||||
|
|
@ -1433,6 +1494,30 @@ version = "0.2.84"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test"
|
||||
version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6db36fc0f9fb209e88fb3642590ae0205bb5a56216dabd963ba15879fe53a30b"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"js-sys",
|
||||
"scoped-tls",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-bindgen-test-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test-macro"
|
||||
version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0734759ae6b3b1717d661fe4f016efcfb9828f5edb4520c18eaee05af3b43be9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.61"
|
||||
|
|
@ -1462,6 +1547,18 @@ dependencies = [
|
|||
"webpki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wee_alloc"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
"libc",
|
||||
"memory_units",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
|
|
|||
|
|
@ -45,6 +45,28 @@ impl Linter {
|
|||
Self { rules }
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn from_json_str(s: &str) -> Self {
|
||||
let rules = serde_json::from_str(s)
|
||||
.ok()
|
||||
.and_then(|v: serde_json::Value| v.get("rules").cloned())
|
||||
.and_then(|v| v.as_object().cloned())
|
||||
.map_or_else(
|
||||
|| RULES.to_vec(),
|
||||
|rules_config| {
|
||||
RULES
|
||||
.iter()
|
||||
.map(|rule| {
|
||||
let value = rules_config.get(rule.name());
|
||||
rule.read_json(value.cloned())
|
||||
})
|
||||
.collect()
|
||||
},
|
||||
);
|
||||
|
||||
Self { rules }
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn from_rules(rules: Vec<RuleEnum>) -> Self {
|
||||
Self { rules }
|
||||
|
|
|
|||
6
crates/oxc_wasm/.gitignore
vendored
Normal file
6
crates/oxc_wasm/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
/target
|
||||
**/*.rs.bk
|
||||
Cargo.lock
|
||||
bin/
|
||||
pkg/
|
||||
wasm-pack.log
|
||||
50
crates/oxc_wasm/Cargo.toml
Normal file
50
crates/oxc_wasm/Cargo.toml
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
[package]
|
||||
name = "oxc_wasm"
|
||||
authors.workspace = true
|
||||
description.workspace = true
|
||||
edition.workspace = true
|
||||
homepage.workspace = true
|
||||
keywords.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
version.workspace = true
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[features]
|
||||
default = ["console_error_panic_hook"]
|
||||
|
||||
[dependencies]
|
||||
oxc_allocator = {path = "../oxc_allocator"}
|
||||
oxc_ast = {path = "../oxc_ast"}
|
||||
oxc_diagnostics = {path = "../oxc_diagnostics"}
|
||||
oxc_linter = {path = "../oxc_linter"}
|
||||
oxc_parser = {path = "../oxc_parser"}
|
||||
oxc_semantic = {path = "../oxc_semantic"}
|
||||
|
||||
miette = {workspace = true, features = ["fancy-no-backtrace"]}
|
||||
serde = {workspace = true, features = ["derive"]}
|
||||
serde_json = {workspace = true}
|
||||
|
||||
wasm-bindgen = {version = "0.2", features = ["serde-serialize"]}
|
||||
|
||||
# The `console_error_panic_hook` crate provides better debugging of panics by
|
||||
# logging them with `console.error`. This is great for development, but requires
|
||||
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
|
||||
# code size when deploying.
|
||||
console_error_panic_hook = {version = "0.1.6", optional = true}
|
||||
|
||||
# `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size
|
||||
# compared to the default allocator's ~10K. It is slower than the default
|
||||
# allocator, however.
|
||||
#
|
||||
# Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now.
|
||||
wee_alloc = {version = "0.4.5", optional = true}
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-test = "0.3.13"
|
||||
|
||||
[profile.release]
|
||||
# Tell `rustc` to optimize for small code size.
|
||||
opt-level = "s"
|
||||
38
crates/oxc_wasm/README.md
Normal file
38
crates/oxc_wasm/README.md
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
## About
|
||||
|
||||
Wasm package for oxc compiler.
|
||||
|
||||
## 🚴 Usage
|
||||
|
||||
```js
|
||||
import oxc from 'oxc-wasm'
|
||||
|
||||
const ast = oxc.main(code, options)
|
||||
```
|
||||
|
||||
### 🛠️ Build with `wasm-pack build`
|
||||
|
||||
```
|
||||
wasm-pack build
|
||||
```
|
||||
|
||||
### 🔬 Test in Headless Browsers with `wasm-pack test`
|
||||
|
||||
```
|
||||
wasm-pack test --headless --firefox
|
||||
```
|
||||
|
||||
### 🎁 Publish to NPM with `wasm-pack publish`
|
||||
|
||||
```
|
||||
wasm-pack publish
|
||||
```
|
||||
|
||||
## 🔋 Batteries Included
|
||||
|
||||
- [`wasm-bindgen`](https://github.com/rustwasm/wasm-bindgen) for communicating
|
||||
between WebAssembly and JavaScript.
|
||||
- [`console_error_panic_hook`](https://github.com/rustwasm/console_error_panic_hook)
|
||||
for logging panic messages to the developer console.
|
||||
- [`wee_alloc`](https://github.com/rustwasm/wee_alloc), an allocator optimized
|
||||
for small code size.
|
||||
62
crates/oxc_wasm/src/driver.rs
Normal file
62
crates/oxc_wasm/src/driver.rs
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
use std::{rc::Rc, sync::Arc};
|
||||
|
||||
use miette::NamedSource;
|
||||
use oxc_allocator::Allocator;
|
||||
use oxc_ast::SourceType;
|
||||
use oxc_diagnostics::Diagnostics;
|
||||
use oxc_linter::Linter;
|
||||
use oxc_parser::Parser;
|
||||
use oxc_semantic::SemanticBuilder;
|
||||
use wasm_bindgen::JsValue;
|
||||
|
||||
pub struct Driver {
|
||||
allocator: Allocator,
|
||||
}
|
||||
|
||||
impl Driver {
|
||||
pub fn new() -> Self {
|
||||
Self { allocator: Allocator::default() }
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
pub fn run(
|
||||
&self,
|
||||
path: &str,
|
||||
source_text: &str,
|
||||
source_type: SourceType,
|
||||
eslintrc: &str,
|
||||
) -> JsValue {
|
||||
let ret = Parser::new(&self.allocator, source_text, source_type)
|
||||
.allow_return_outside_function(true)
|
||||
.parse();
|
||||
|
||||
let program = self.allocator.alloc(ret.program);
|
||||
|
||||
let diagnostics = Diagnostics::default();
|
||||
let semantic = SemanticBuilder::new(source_type).build(program, Rc::new(ret.trivias));
|
||||
let mut diagnostics = diagnostics.into_inner();
|
||||
|
||||
let source = Arc::new(NamedSource::new(path, source_text.to_string()));
|
||||
|
||||
diagnostics.extend(
|
||||
Linter::from_json_str(eslintrc)
|
||||
.run(&Rc::new(semantic), source_text, false)
|
||||
.into_iter()
|
||||
.map(|m| m.error.with_source_code(source.clone()))
|
||||
.chain(ret.errors),
|
||||
);
|
||||
|
||||
if diagnostics.is_empty() {
|
||||
if let Ok(ast) = JsValue::from_serde(program) {
|
||||
return ast;
|
||||
}
|
||||
}
|
||||
|
||||
let result = diagnostics
|
||||
.into_iter()
|
||||
.map(|error| format!("{error:?}"))
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n");
|
||||
JsValue::from_str(&result)
|
||||
}
|
||||
}
|
||||
50
crates/oxc_wasm/src/lib.rs
Normal file
50
crates/oxc_wasm/src/lib.rs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
mod driver;
|
||||
mod utils;
|
||||
|
||||
use driver::Driver;
|
||||
use oxc_ast::SourceType;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use utils::set_panic_hook;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[derive(Deserialize, Serialize, PartialEq, Eq)]
|
||||
pub enum Language {
|
||||
#[serde(rename = "javascript")]
|
||||
JavaScript,
|
||||
#[serde(rename = "typescript")]
|
||||
TypeScript,
|
||||
}
|
||||
|
||||
impl Default for Language {
|
||||
fn default() -> Self {
|
||||
Self::TypeScript
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Default)]
|
||||
pub struct Options {
|
||||
pub language: Option<Language>,
|
||||
|
||||
pub jsx: Option<bool>,
|
||||
|
||||
pub eslintrc: Option<String>,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
#[must_use]
|
||||
#[allow(deprecated)]
|
||||
pub fn main(text: &str, js_options: &JsValue) -> JsValue {
|
||||
set_panic_hook();
|
||||
let options: Options = js_options.into_serde().unwrap_or_default();
|
||||
let path_str = format!(
|
||||
"test.{}{}",
|
||||
if matches!(options.language, Some(Language::TypeScript)) { "ts" } else { "js" },
|
||||
if options.jsx.unwrap_or_default() { "x" } else { "" }
|
||||
);
|
||||
|
||||
let source_type = SourceType::from_path(&path_str).unwrap_or_default();
|
||||
|
||||
let driver = Driver::new();
|
||||
|
||||
driver.run(&path_str, text, source_type, &options.eslintrc.unwrap_or_default())
|
||||
}
|
||||
10
crates/oxc_wasm/src/utils.rs
Normal file
10
crates/oxc_wasm/src/utils.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
pub fn set_panic_hook() {
|
||||
// When the `console_error_panic_hook` feature is enabled, we can call the
|
||||
// `set_panic_hook` function at least once during initialization, and then
|
||||
// we will get better error messages if our code ever panics.
|
||||
//
|
||||
// For more details see
|
||||
// https://github.com/rustwasm/console_error_panic_hook#readme
|
||||
#[cfg(feature = "console_error_panic_hook")]
|
||||
console_error_panic_hook::set_once();
|
||||
}
|
||||
Loading…
Reference in a new issue