mirror of
https://github.com/swc-project/swc.git
synced 2024-12-23 13:51:19 +03:00
Move config from libswc to node-swc
This commit is contained in:
parent
0f0dc1451a
commit
9361e96d5b
10
Cargo.toml
10
Cargo.toml
@ -13,14 +13,10 @@ description = "Speedy web compiler"
|
||||
name = "swc"
|
||||
|
||||
[dependencies]
|
||||
rayon = "1.0.3"
|
||||
swc_atoms = { version = "0.1", path ="./atoms" }
|
||||
swc_common = { version = "0.1", path ="./common" }
|
||||
swc_ecmascript = { version = "0.1", path ="./ecmascript" }
|
||||
swc_atoms = { path ="./atoms" }
|
||||
swc_common = { path ="./common" }
|
||||
swc_ecmascript = { path ="./ecmascript" }
|
||||
sourcemap = "2.2"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
fnv = "1"
|
||||
|
||||
[profile.bench]
|
||||
lto = true
|
||||
|
122
src/config.rs
122
src/config.rs
@ -1,122 +0,0 @@
|
||||
use crate::Compiler;
|
||||
use atoms::JsWord;
|
||||
use common::FileName;
|
||||
use ecmascript::{
|
||||
ast::{Expr, ModuleItem, Stmt},
|
||||
parser::Syntax,
|
||||
transforms::{react, InlineGlobals},
|
||||
};
|
||||
use fnv::FnvHashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{collections::HashMap, env};
|
||||
|
||||
/// `.swcrc` file
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
pub struct Config {
|
||||
#[serde(default)]
|
||||
pub jsc: JscConfig,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
pub struct JscConfig {
|
||||
#[serde(rename = "parser", default)]
|
||||
pub syntax: Syntax,
|
||||
#[serde(default)]
|
||||
pub transform: TrnasformConfig,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
pub struct TrnasformConfig {
|
||||
#[serde(default)]
|
||||
pub react: react::Options,
|
||||
#[serde(default)]
|
||||
pub optimizer: Option<OptimizerConfig>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
pub struct OptimizerConfig {
|
||||
#[serde(default)]
|
||||
pub globals: Option<GlobalPassOption>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
pub struct GlobalPassOption {
|
||||
#[serde(default)]
|
||||
pub vars: FnvHashMap<String, String>,
|
||||
}
|
||||
|
||||
impl GlobalPassOption {
|
||||
pub fn build(self, c: &Compiler) -> InlineGlobals {
|
||||
fn mk_map(
|
||||
c: &Compiler,
|
||||
values: impl Iterator<Item = (String, String)>,
|
||||
is_env: bool,
|
||||
) -> HashMap<JsWord, Expr> {
|
||||
let mut m = HashMap::new();
|
||||
|
||||
for (k, v) in values {
|
||||
let v = if is_env {
|
||||
format!("'{}'", v)
|
||||
} else {
|
||||
(*v).into()
|
||||
};
|
||||
|
||||
let mut module = c
|
||||
.parse_js(
|
||||
FileName::Custom(format!("GLOBAL_{}", k)),
|
||||
Default::default(),
|
||||
&v,
|
||||
)
|
||||
.unwrap_or_else(|err| panic!("failed to parse globals.{}: {:?}", k, err));
|
||||
let expr = match module.body.pop().unwrap() {
|
||||
ModuleItem::Stmt(Stmt::Expr(box expr)) => expr,
|
||||
_ => panic!("{} is not a valid expression", v),
|
||||
};
|
||||
|
||||
m.insert((*k).into(), expr);
|
||||
}
|
||||
|
||||
m
|
||||
}
|
||||
|
||||
InlineGlobals {
|
||||
globals: mk_map(c, self.vars.into_iter(), false),
|
||||
envs: mk_map(c, env::vars(), true),
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use ecmascript::parser::TsConfig;
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
println!(
|
||||
"{}",
|
||||
serde_json::to_string_pretty(&Config {
|
||||
jsc: JscConfig {
|
||||
syntax: Syntax::Typescript(TsConfig {
|
||||
..Default::default()
|
||||
}),
|
||||
transform: TrnasformConfig {
|
||||
react: react::Options {
|
||||
..Default::default()
|
||||
},
|
||||
optimizer: Some(OptimizerConfig {
|
||||
globals: Some(GlobalPassOption {
|
||||
vars: {
|
||||
let mut map = FnvHashMap::default();
|
||||
map.insert("__DEBUG__".into(), "true".into());
|
||||
map
|
||||
}
|
||||
}),
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
.unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
152
src/lib.rs
152
src/lib.rs
@ -1,157 +1,5 @@
|
||||
#![feature(box_syntax)]
|
||||
#![feature(box_patterns)]
|
||||
|
||||
extern crate fnv;
|
||||
extern crate rayon;
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
pub extern crate sourcemap;
|
||||
pub extern crate swc_atoms as atoms;
|
||||
pub extern crate swc_common as common;
|
||||
pub extern crate swc_ecmascript as ecmascript;
|
||||
|
||||
use self::{
|
||||
common::{errors::Handler, sync::Lrc, FileName, Globals, SourceMap, GLOBALS},
|
||||
config::Config,
|
||||
ecmascript::{
|
||||
ast::Module,
|
||||
codegen::{self, Emitter},
|
||||
parser::{Parser, Session as ParseSess, SourceFileInput, Syntax},
|
||||
},
|
||||
};
|
||||
use sourcemap::SourceMapBuilder;
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
collections::HashMap,
|
||||
fs::File,
|
||||
io,
|
||||
path::{Path, PathBuf},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
pub mod config;
|
||||
|
||||
pub struct Compiler {
|
||||
pub globals: Globals,
|
||||
pub cm: Lrc<SourceMap>,
|
||||
handler: Handler,
|
||||
config_caches: RefCell<HashMap<PathBuf, Arc<Config>>>,
|
||||
}
|
||||
|
||||
impl Compiler {
|
||||
pub fn new(cm: Lrc<SourceMap>, handler: Handler) -> Self {
|
||||
Compiler {
|
||||
cm,
|
||||
handler,
|
||||
globals: Globals::new(),
|
||||
config_caches: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn config_for_file(&self, path: &Path) -> Result<Arc<Config>, io::Error> {
|
||||
assert!(!path.is_file());
|
||||
|
||||
let mut parent = path.parent();
|
||||
while let Some(dir) = parent {
|
||||
let swcrc = dir.join(".swcrc");
|
||||
if let Some(c) = self.config_caches.borrow().get(&swcrc) {
|
||||
return Ok(c.clone());
|
||||
}
|
||||
|
||||
if swcrc.exists() {
|
||||
let mut r = File::open(&swcrc)?;
|
||||
let config: Config = serde_json::from_reader(r)?;
|
||||
let arc = Arc::new(config);
|
||||
self.config_caches.borrow_mut().insert(swcrc, arc.clone());
|
||||
return Ok(arc);
|
||||
}
|
||||
|
||||
parent = dir.parent();
|
||||
}
|
||||
|
||||
Ok(Default::default())
|
||||
}
|
||||
|
||||
pub fn run<F, T>(&self, op: F) -> T
|
||||
where
|
||||
F: FnOnce() -> T,
|
||||
{
|
||||
GLOBALS.set(&self.globals, op)
|
||||
}
|
||||
|
||||
pub fn parse_js(&self, name: FileName, syntax: Syntax, src: &str) -> Result<Module, ()> {
|
||||
self.run(|| {
|
||||
let fm = self.cm.new_source_file(name, src.into());
|
||||
|
||||
let session = ParseSess {
|
||||
handler: &self.handler,
|
||||
};
|
||||
Parser::new(session, syntax, SourceFileInput::from(&*fm))
|
||||
.parse_module()
|
||||
.map_err(|e| {
|
||||
e.emit();
|
||||
()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/// TODO
|
||||
pub fn parse_js_file(&self, syntax: Option<Syntax>, path: &Path) -> Result<Module, ()> {
|
||||
self.run(|| {
|
||||
let syntax = syntax.unwrap_or_else(|| {
|
||||
self.config_for_file(path)
|
||||
.map(|c| c.jsc.syntax)
|
||||
.expect("failed to load config")
|
||||
});
|
||||
|
||||
let fm = self.cm.load_file(path).expect("failed to load file");
|
||||
|
||||
let session = ParseSess {
|
||||
handler: &self.handler,
|
||||
};
|
||||
Parser::new(session, syntax, SourceFileInput::from(&*fm))
|
||||
.parse_module()
|
||||
.map_err(|e| {
|
||||
e.emit();
|
||||
()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns code, sourcemap
|
||||
pub fn emit_module(
|
||||
&self,
|
||||
module: &Module,
|
||||
cfg: codegen::Config,
|
||||
) -> io::Result<(String, sourcemap::SourceMap)> {
|
||||
self.run(|| {
|
||||
let mut src_map_builder = SourceMapBuilder::new(None);
|
||||
let src = {
|
||||
let mut buf = vec![];
|
||||
{
|
||||
let handlers = box MyHandlers;
|
||||
let mut emitter = Emitter {
|
||||
cfg,
|
||||
cm: self.cm.clone(),
|
||||
wr: box swc_ecmascript::codegen::text_writer::JsWriter::new(
|
||||
self.cm.clone(),
|
||||
"\n",
|
||||
&mut buf,
|
||||
&mut src_map_builder,
|
||||
),
|
||||
handlers,
|
||||
pos_of_leading_comments: Default::default(),
|
||||
};
|
||||
|
||||
emitter.emit_module(&module)?;
|
||||
}
|
||||
String::from_utf8(buf).unwrap()
|
||||
};
|
||||
Ok((src, src_map_builder.into_sourcemap()))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct MyHandlers;
|
||||
|
||||
impl swc_ecmascript::codegen::Handlers for MyHandlers {}
|
||||
|
Loading…
Reference in New Issue
Block a user