Add index.d.ts and export inline globals pass (#90)

This commit is contained in:
강동윤 2018-12-22 17:41:01 +09:00 committed by GitHub
parent 946a32adf8
commit 5bea4a6138
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 108 additions and 9 deletions

40
ffi/lib/index.d.ts vendored Normal file
View File

@ -0,0 +1,40 @@
declare module "swc" {
/**
* Options for trasnform.
*/
export interface TransformOption {
/**
*
* Defaults to false.
*/
readonly optimize?: boolean;
readonly globals?: GlobalPassOption;
}
/**
* Options for inline-global pass.
*/
export interface GlobalPassOption {
/**
* Global variables.
*
* e.g. { __DEBUG__: true }
*/
readonly vars?: { [key: string]: string };
}
export interface Output {
/**
* Transformed code
*/
readonly code: string;
/**
* Sourcemap (not base64 encoded)
*/
readonly map: string;
}
export function transform(src: string, options?: TransformOption): Output;
export function transformFileSync(path: string, options?: TransformOption): Output;
}

View File

@ -21,6 +21,7 @@ serde_derive = "1"
neon = "0.2.0" neon = "0.2.0"
neon-serde = "0.1.1" neon-serde = "0.1.1"
sourcemap = "2" sourcemap = "2"
fnv = "1"
swc = { git = "https://github.com/swc-project/swc.git" } swc = { git = "https://github.com/swc-project/swc.git" }
[profile.bench] [profile.bench]

View File

@ -1,5 +1,9 @@
#![feature(box_syntax)]
#![feature(box_patterns)]
#[macro_use] #[macro_use]
extern crate neon; extern crate neon;
extern crate fnv;
extern crate neon_serde; extern crate neon_serde;
extern crate serde; extern crate serde;
#[macro_use] #[macro_use]
@ -7,16 +11,18 @@ extern crate serde_derive;
extern crate sourcemap; extern crate sourcemap;
extern crate swc; extern crate swc;
use fnv::FnvHashMap;
use neon::prelude::*; use neon::prelude::*;
use std::{path::Path, sync::Arc}; use std::{collections::HashMap, env, path::Path, sync::Arc};
use swc::{ use swc::{
atoms::JsWord,
common::{ common::{
self, errors::Handler, sync::Lrc, FileName, FilePathMapping, Fold, FoldWith, SourceMap, self, errors::Handler, sync::Lrc, FileName, FilePathMapping, Fold, FoldWith, SourceMap,
}, },
ecmascript::{ ecmascript::{
ast::Module, ast::{Expr, Module, ModuleItem, Stmt},
codegen, codegen,
transforms::{compat, hygiene, simplifier}, transforms::{compat, hygiene, simplifier, InlineGlobals},
}, },
Compiler, Compiler,
}; };
@ -42,6 +48,48 @@ fn parse(mut cx: FunctionContext) -> JsResult<JsObject> {
#[derive(Default, Deserialize)] #[derive(Default, Deserialize)]
struct TransformOption { struct TransformOption {
optimize: bool, optimize: bool,
globals: Option<GlobalPassOption>,
}
#[derive(Default, Deserialize)]
struct GlobalPassOption {
vars: FnvHashMap<String, String>,
}
impl GlobalPassOption {
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)), &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),
}
}
} }
fn transform(mut cx: FunctionContext) -> JsResult<JsObject> { fn transform(mut cx: FunctionContext) -> JsResult<JsObject> {
@ -64,7 +112,7 @@ fn transform(mut cx: FunctionContext) -> JsResult<JsObject> {
let module = c let module = c
.parse_js(FileName::Anon(0), &source.value()) .parse_js(FileName::Anon(0), &source.value())
.expect("failed to parse module"); .expect("failed to parse module");
let module = c.run(|| transform_module(cm.clone(), module, options)); let module = c.run(|| transform_module(&c, module, options));
let (code, map) = c let (code, map) = c
.emit_module( .emit_module(
@ -110,7 +158,7 @@ fn transform_file(mut cx: FunctionContext) -> JsResult<JsObject> {
let module = c let module = c
.parse_js_file(Path::new(&path.value())) .parse_js_file(Path::new(&path.value()))
.expect("failed to parse module"); .expect("failed to parse module");
let module = c.run(|| transform_module(cm.clone(), module, options)); let module = c.run(|| transform_module(&c, module, options));
let (code, map) = c let (code, map) = c
.emit_module( .emit_module(
@ -136,9 +184,18 @@ fn transform_file(mut cx: FunctionContext) -> JsResult<JsObject> {
Ok(obj) Ok(obj)
} }
fn transform_module(cm: Lrc<SourceMap>, module: Module, options: TransformOption) -> Module { fn transform_module(c: &Compiler, module: Module, options: TransformOption) -> Module {
let helpers = Arc::new(compat::helpers::Helpers::default()); let helpers = Arc::new(compat::helpers::Helpers::default());
let module = {
let opts = if let Some(opts) = options.globals {
opts
} else {
Default::default()
};
module.fold_with(&mut opts.build(c))
};
let module = if options.optimize { let module = if options.optimize {
module.fold_with(&mut simplifier()) module.fold_with(&mut simplifier())
} else { } else {
@ -154,7 +211,7 @@ fn transform_module(cm: Lrc<SourceMap>, module: Module, options: TransformOption
.fold_with(&mut hygiene()); .fold_with(&mut hygiene());
module.fold_with(&mut compat::helpers::InjectHelpers { module.fold_with(&mut compat::helpers::InjectHelpers {
cm, cm: c.cm.clone(),
helpers: helpers.clone(), helpers: helpers.clone(),
}) })
} }
@ -162,6 +219,6 @@ fn transform_module(cm: Lrc<SourceMap>, module: Module, options: TransformOption
register_module!(mut cx, { register_module!(mut cx, {
cx.export_function("parse", parse)?; cx.export_function("parse", parse)?;
cx.export_function("transform", transform)?; cx.export_function("transform", transform)?;
cx.export_function("transformFile", transform_file)?; cx.export_function("transformFileSync", transform_file)?;
Ok(()) Ok(())
}); });

View File

@ -1,6 +1,6 @@
{ {
"name": "swc", "name": "swc",
"version": "1.0.0-alpha.2", "version": "1.0.0-alpha.3",
"description": "Super-fast alternative for babel", "description": "Super-fast alternative for babel",
"main": "lib/index.js", "main": "lib/index.js",
"author": "강동윤 <kdy1@outlook.kr>", "author": "강동윤 <kdy1@outlook.kr>",
@ -8,6 +8,7 @@
"dependencies": { "dependencies": {
"neon-cli": "^0.2.0" "neon-cli": "^0.2.0"
}, },
"types": "./lib/index.d.ts",
"scripts": { "scripts": {
"install": "neon build --release" "install": "neon build --release"
}, },