More works (#66)

ecma_transforms:
 - implement es2015::instanceof
 - implement es2015::typeof_symbol
 - implement inline_globals pass

ecma_parser:
 - `PResult<T>` is now `Result<T, ()>` and `Err(())` means that an error is emitted.
 - add docs
This commit is contained in:
강동윤 2018-11-18 14:00:07 +09:00 committed by GitHub
parent 6f8ded406b
commit 1d0c78de6c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
64 changed files with 664 additions and 213 deletions

View File

@ -4,12 +4,16 @@
name = "swc"
version = "0.1.0"
authors = ["강동윤 <kdy1@outlook.kr>"]
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"
documentation = "https://swc-project.github.io/rustdoc/swc/"
description = "Speedy web compiler"
[[bin]]
name = "swc"
[dependencies]
libswc = { path = "./libswc" }
libswc = { version = "0.1", path = "./libswc" }
rayon = "1.0.3"
slog = "2"
slog-envlogger = "2.1"

View File

@ -24,9 +24,12 @@ RUSTFLAGS='--cfg procmacro2_semver_exempt --cfg parallel_queries' cargo install
New generation javascript to old-days javascript.
- es3
- [x] member expression literals
- [x] peroperty literals
- [ ] reserved words
- [x] member-expression-literals
- [x] property-literals
- [ ] reserved-words
- es5
- [ ] property-mutators
- es2015
- [ ] arrow-functions
@ -38,7 +41,7 @@ New generation javascript to old-days javascript.
- [ ] duplicate-keys
- [ ] for-of
- [ ] function-name
- [ ] instanceof
- [x] instanceof
- [ ] literals
- [ ] new-target
- [ ] object-super
@ -47,17 +50,16 @@ New generation javascript to old-days javascript.
- [x] spread
- [x] sticky regex (`y` flag)
- [ ] template-literals
- [ ] typeof-symbol
- [x] typeof-symbol
- [ ] unicode-regex
- es2016
- [x] operator `**`
- [x] exponentiation-operator
- es2017
- [ ] async-to-generator
- es2018
- [ ] parser
- [ ] async-generator-functions
- [ ] dotall-regex
- [ ] object-rest-spread

View File

@ -3,6 +3,10 @@ name = "swc_atoms"
build = "build.rs"
version = "0.1.0"
authors = ["강동윤 <kdy1@outlook.kr>"]
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"
documentation = "https://swc-project.github.io/rustdoc/swc_atoms/"
description = "Atoms for the swc project."
[dependencies]
string_cache = "0.7"

View File

@ -1,4 +1,5 @@
Infinity
NODE_ENV
NaN
Object
RegExp
@ -24,6 +25,7 @@ delete
do
else
enum
env
export
extends
false
@ -46,6 +48,7 @@ null
of
package
private
process
protected
public
return

View File

@ -1,10 +1,14 @@
[package]
name = "swc_common"
version = "0.1.0"
version = "0.1.1"
authors = ["강동윤 <kdy1@outlook.kr>"]
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"
documentation = "https://swc-project.github.io/rustdoc/swc_common/"
description = "Common utilities for the swc project."
[dependencies]
ast_node = { path = "../macros/ast_node" }
ast_node = { version = "0.1", path = "../macros/ast_node" }
string_cache = "0.7"
either = "1.5"
rustc-ap-rustc_errors = "297"

View File

@ -2,11 +2,15 @@
name = "swc_ecmascript"
version = "0.1.0"
authors = ["강동윤 <kdy1@outlook.kr>"]
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"
documentation = "https://swc-project.github.io/rustdoc/swc_ecmascript/"
description = "Ecmascript"
[dependencies]
swc_ecma_ast = { path = "./ast" }
swc_ecma_codegen = { path = "./codegen" }
swc_ecma_parser = { path = "./parser" }
swc_ecma_transforms = { path = "./transforms" }
swc_ecma_ast = { version = "0.1", path ="./ast" }
swc_ecma_codegen = { version = "0.1", path ="./codegen" }
swc_ecma_parser = { version = "0.2", path ="./parser" }
swc_ecma_transforms = { version = "0.1", path ="./transforms" }
[dev-dependencies]

View File

@ -2,9 +2,13 @@
name = "swc_ecma_ast"
version = "0.1.0"
authors = ["강동윤 <kdy1@outlook.kr>"]
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"
documentation = "https://swc-project.github.io/rustdoc/swc_ecma_ast/"
description = "Ecmascript ast."
[dependencies]
swc_atoms = { path = "../../atoms" }
swc_common = { path = "../../common" }
enum_kind = { path = "../../macros/enum_kind" }
string_enum = { path = "../../macros/string_enum" }
swc_atoms = { version = "0.1", path ="../../atoms" }
swc_common = { version = "0.1", path ="../../common" }
enum_kind = { version = "0.1", path ="../../macros/enum_kind" }
string_enum = { version = "0.1", path ="../../macros/string_enum" }

View File

@ -1,17 +1,21 @@
[package]
name = "swc_ecma_codegen"
version = "0.1.0"
version = "0.1.1"
authors = ["강동윤 <kdy1@outlook.kr>"]
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"
documentation = "https://swc-project.github.io/rustdoc/swc_ecma_codegen/"
description = "Ecmascript code generator for the swc project."
[dependencies]
bitflags = "1"
swc_atoms = { path = "../../atoms" }
swc_common = { path = "../../common" }
swc_ecma_ast = { path = "../ast" }
swc_ecma_codegen_macros = { path = "./macros" }
swc_atoms = { version = "0.1", path ="../../atoms" }
swc_common = { version = "0.1", path ="../../common" }
swc_ecma_ast = { version = "0.1", path ="../ast" }
swc_ecma_codegen_macros = { version = "0.1", path ="./macros" }
sourcemap = "2.2"
[dev-dependencies]
testing = { path = "../../testing" }
testing = { version = "0.1", path ="../../testing" }
slog = "2"
swc_ecma_parser = { path = "../parser" }
swc_ecma_parser = { version = "0.2", path ="../parser" }

View File

@ -2,13 +2,17 @@
name = "swc_ecma_codegen_macros"
version = "0.1.0"
authors = ["강동윤 <kdy1@outlook.kr>"]
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"
documentation = "https://swc-project.github.io/rustdoc/swc_ecma_codegen_macros/"
description = "Macros for swc_ecma_codegen."
[lib]
proc-macro = true
[dependencies]
swc_macros_common = { path = "../../../macros/common" }
swc_macros_common = { version = "0.1", path ="../../../macros/common" }
pmutil = "0.2"
proc-macro2 = "0.4"

View File

@ -87,13 +87,7 @@ fn test_from_to(from: &str, to: &str) {
(&*src).into(),
));
match res {
Ok(res) => Ok(res),
Err(err) => {
err.emit();
Err(())
}
}
res
})
}
let res = with_parser(Path::new("test.js"), from, |p| p.parse_module()).unwrap();

View File

@ -175,19 +175,9 @@ fn error_tests(tests: &mut Vec<TestDescAndFn>) -> Result<(), io::Error> {
// Parse source
if module {
emitter
.emit_module(&parser.parse_module().map_err(|e| {
e.emit();
()
})?)
.unwrap();
emitter.emit_module(&parser.parse_module()?).unwrap();
} else {
emitter
.emit_script(&parser.parse_script().map_err(|e| {
e.emit();
()
})?)
.unwrap();
emitter.emit_script(&parser.parse_script()?).unwrap();
}
}
let ref_file = format!("{}", ref_dir.join(&file_name).display());

View File

@ -1,18 +1,22 @@
[package]
name = "swc_ecma_parser"
version = "0.1.0"
version = "0.2.2"
authors = ["강동윤 <kdy1@outlook.kr>"]
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"
documentation = "https://swc-project.github.io/rustdoc/swc_ecma_parser/"
description = "Feature-complete es2019 parser."
[dependencies]
swc_atoms = { path = "../../atoms" }
swc_common = { path = "../../common" }
swc_ecma_ast = { path = "../ast" }
swc_ecma_parser_macros = { path = "./macros" }
enum_kind = { path = "../../macros/enum_kind" }
swc_atoms = { version = "0.1", path ="../../atoms" }
swc_common = { version = "0.1", path ="../../common" }
swc_ecma_ast = { version = "0.1", path ="../ast" }
swc_ecma_parser_macros = { version = "0.1", path ="./macros" }
enum_kind = { version = "0.1", path ="../../macros/enum_kind" }
unicode-xid = "0.1"
slog = "2.1"
either = { version = "1.4" }
[dev-dependencies]
testing = { path = "../../testing" }
testing = { version = "0.1", path ="../../testing" }

View File

@ -2,12 +2,16 @@
name = "swc_ecma_parser_macros"
version = "0.1.0"
authors = ["강동윤 <kdy1@outlook.kr>"]
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"
documentation = "https://swc-project.github.io/rustdoc/swc_ecma_parser_macros/"
description = "Macros for swc_ecma_parser."
[lib]
proc-macro = true
[dependencies]
swc_macros_common = { path = "../../../macros/common" }
swc_macros_common = { version = "0.1", path ="../../../macros/common" }
proc-macro2 = "0.4.4"
[dependencies.syn]

View File

@ -1,12 +1,10 @@
//! Ported from [babylon/util/identifier.js][]
//!
//!
//! [babylon/util/identifier.js]:\
//! https://github.com/babel/babel/blob/master/packages/babylon/src/util/identifier.js
//!
//!
//! Note: Currently this use xid instead of id because unicode_xid crate
//! exists.
//!
//!
//! [babylon/util/identifier.js]:https://github.com/babel/babel/blob/master/packages/babylon/src/util/identifier.js
use super::{input::Input, LexResult, Lexer};
use error::{ErrorToDiag, SyntaxError};
use swc_common::{BytePos, Span};

View File

@ -1,3 +1,68 @@
//! es2019 parser
//!
//! # Features
//!
//! ## Heavily tested
//!
//! Passes almost all tests from [tc39/test262][].
//!
//! ## Error reporting
//!
//! ```sh
//! error: 'implements', 'interface', 'let', 'package', 'private', 'protected', 'public', 'static', or 'yield' cannot be used as an identifier in strict mode
//! --> invalid.js:3:10
//! |
//! 3 | function yield() {
//! | ^^^^^
//! ```
//!
//! # Example
//!
//! ```
//! #[macro_use]
//! extern crate slog;
//! extern crate swc_common;
//! extern crate swc_ecma_parser;
//! use swc_common::{
//! errors::{ColorConfig, Handler},
//! sync::Lrc,
//! FileName, FilePathMapping, SourceMap,
//! };
//! use swc_ecma_parser::{Parser, Session, SourceFileInput};
//!
//! fn main() {
//! swc_common::GLOBALS.set(&swc_common::Globals::new(), || {
//! let cm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
//! let handler =
//! Handler::with_tty_emitter(ColorConfig::Auto, true, false, Some(cm.clone()));
//! let logger = slog::Logger::root(slog::Discard, o!());
//!
//! let session = Session {
//! handler: &handler,
//! logger: &logger,
//! cfg: Default::default(),
//! };
//!
//! // Real usage
//! // let fm = cm
//! // .load_file(Path::new("test.js"))
//! // .expect("failed to load test.js");
//!
//! let fm = cm.new_source_file(
//! FileName::Custom("test.js".into()),
//! "function foo() {}".into(),
//! );
//!
//! let mut parser = Parser::new(session, SourceFileInput::from(&*fm));
//!
//! let _module = parser.parse_module().expect("failed to parser module");
//! });
//! }
//! ```
//!
//!
//! [tc39/test262]:https://github.com/tc39/test262
#![feature(box_syntax)]
#![feature(box_patterns)]
#![feature(const_fn)]

View File

@ -434,19 +434,15 @@ mod tests {
fn lhs(s: &'static str) -> Box<Expr> {
test_parser(s, |p| {
p.parse_lhs_expr().unwrap_or_else(|err| {
err.emit();
unreachable!("failed to parse a left-hand-side expression")
})
p.parse_lhs_expr()
.unwrap_or_else(|()| unreachable!("failed to parse a left-hand-side expression"))
})
}
fn expr(s: &'static str) -> Box<Expr> {
test_parser(s, |p| {
p.parse_expr().unwrap_or_else(|err| {
err.emit();
unreachable!("failed to parse an expression")
})
p.parse_expr()
.unwrap_or_else(|()| unreachable!("failed to parse an expression"))
})
}

View File

@ -206,11 +206,8 @@ mod tests {
fn bin(s: &'static str) -> Box<Expr> {
test_parser(s, |p| {
p.parse_bin_expr().unwrap_or_else(|err| {
err.emit();
panic!("failed to parse '{}' as a binary expression", s)
})
p.parse_bin_expr()
.unwrap_or_else(|()| panic!("failed to parse '{}' as a binary expression", s))
})
}

View File

@ -3,37 +3,29 @@ use swc_common::DUMMY_SP as span;
fn lhs(s: &'static str) -> Box<Expr> {
test_parser(s, |p| {
p.parse_lhs_expr().unwrap_or_else(|err| {
err.emit();
unreachable!("failed to parse lhs expression")
})
p.parse_lhs_expr()
.unwrap_or_else(|()| unreachable!("failed to parse lhs expression"))
})
}
fn new_expr(s: &'static str) -> Box<Expr> {
test_parser(s, |p| {
p.parse_new_expr().unwrap_or_else(|err| {
err.emit();
unreachable!("failed to parse an expression")
})
p.parse_new_expr()
.unwrap_or_else(|()| unreachable!("failed to parse an expression"))
})
}
fn member_expr(s: &'static str) -> Box<Expr> {
test_parser(s, |p| {
p.parse_member_expr().unwrap_or_else(|err| {
err.emit();
unreachable!("failed to parse an expression")
})
p.parse_member_expr()
.unwrap_or_else(|()| unreachable!("failed to parse an expression"))
})
}
fn expr(s: &'static str) -> Box<Expr> {
test_parser(s, |p| {
p.parse_expr().unwrap_or_else(|err| {
err.emit();
unreachable!("failed to parse an expression")
})
p.parse_expr()
.unwrap_or_else(|()| unreachable!("failed to parse an expression"))
})
}

View File

@ -147,11 +147,13 @@ macro_rules! cur {
if is_err_token {
match $p.input.bump() {
$crate::token::Token::Error(e) => {
let err: Result<!, _> = Err($crate::error::ErrorToDiag {
::swc_common::errors::DiagnosticBuilder::from($crate::error::ErrorToDiag {
handler: &$p.session.handler,
span: e.span,
error: e.error,
});
})
.emit();
let err: Result<!, _> = Err(());
err?
}
_ => unreachable!(),
@ -160,10 +162,14 @@ macro_rules! cur {
match $p.input.cur() {
Some(c) => Ok(c),
None => Err($crate::error::Eof {
last,
handler: &$p.session.handler,
}),
None => {
::swc_common::errors::DiagnosticBuilder::from($crate::error::Eof {
last,
handler: &$p.session.handler,
})
.emit();
Err(())
}
}
}};
}
@ -181,11 +187,15 @@ Current token is {:?}",
let last = Span::new(pos, pos, Default::default());
match $p.input.peek() {
Some(c) => Ok(c),
None => Err($crate::error::Eof {
//TODO: Use whole span
last,
handler: &$p.session.handler,
}),
None => {
::swc_common::errors::DiagnosticBuilder::from($crate::error::Eof {
//TODO: Use whole span
last,
handler: &$p.session.handler,
})
.emit();
Err(())
}
}
}};
}
@ -254,12 +264,13 @@ macro_rules! syntax_error {
};
($p:expr, $span:expr, $err:expr) => {{
let err = $crate::error::ErrorToDiag {
::swc_common::errors::DiagnosticBuilder::from($crate::error::ErrorToDiag {
handler: $p.session.handler,
span: $span,
error: $err,
};
let res: Result<!, _> = Err(err);
})
.emit();
let res: Result<!, _> = Err(());
res?
}};
}

View File

@ -7,7 +7,7 @@ use lexer::{Input, Lexer};
use parser_macros::parser;
use std::ops::{Deref, DerefMut};
use swc_atoms::JsWord;
use swc_common::{errors::DiagnosticBuilder, BytePos, Span};
use swc_common::{BytePos, Span};
use token::*;
use Context;
use Session;
@ -23,7 +23,8 @@ mod pat;
mod stmt;
mod util;
pub type PResult<'a, T> = Result<T, DiagnosticBuilder<'a>>;
/// When error ocurred, error is emiited and parser returnes Err(()).
pub type PResult<'a, T> = Result<T, ()>;
/// EcmaScript parser.
pub struct Parser<'a, I: Input> {
@ -95,6 +96,6 @@ fn module_legacy() {
let res = f.parse_module();
assert!(f.ctx().module);
assert!(f.ctx().strict);
let _ = res.expect_err("!").cancel();
let _ = res.expect_err("!");
});
}

View File

@ -268,10 +268,6 @@ impl<'a, I: Input> Parser<'a, I> {
});
if !self.ctx().in_function {
match stmt {
Ok(_) => {}
Err(e) => e.emit(),
}
syntax_error!(span!(start), SyntaxError::ReturnNotAllowed)
} else {
stmt
@ -731,18 +727,14 @@ mod tests {
fn stmt(s: &'static str) -> Stmt {
test_parser(s, |p| {
p.parse_stmt(true).unwrap_or_else(|err| {
err.emit();
unreachable!("failed to parse a statement")
})
p.parse_stmt(true)
.unwrap_or_else(|()| unreachable!("failed to parse a statement"))
})
}
fn expr(s: &'static str) -> Box<Expr> {
test_parser(s, |p| {
p.parse_expr().unwrap_or_else(|err| {
err.emit();
unreachable!("failed to parse an expression")
})
p.parse_expr()
.unwrap_or_else(|()| unreachable!("failed to parse an expression"))
})
}

View File

@ -1,3 +1,9 @@
error: Unexpected eof
--> $DIR/tests/test262-parser/fail/03d13b6c40f6aaea.js:1:13
|
1 | [{a=0},...0]
| ^
error: Unexpected token
--> $DIR/tests/test262-parser/fail/03d13b6c40f6aaea.js:1:3
|

View File

@ -1,3 +1,9 @@
error: Unexpected eof
--> $DIR/tests/test262-parser/fail/0889113e04d3203f.js:1:6
|
1 | class
| ^
error: Expected ident
--> $DIR/tests/test262-parser/fail/0889113e04d3203f.js:1:1
|

View File

@ -1,3 +1,9 @@
error: Unexpected eof
--> $DIR/tests/test262-parser/fail/0f175471e2f0c3d5.js:1:6
|
1 | class
| ^
error: Expected ident
--> $DIR/tests/test262-parser/fail/0f175471e2f0c3d5.js:1:1
|

View File

@ -1,3 +1,9 @@
error: Unexpected eof
--> $DIR/tests/test262-parser/fail/245843abef9e72e7.js:1:2
|
1 | [
| ^
error: Expected RBracket
--> $DIR/tests/test262-parser/fail/245843abef9e72e7.js:1:1
|

View File

@ -1,3 +1,9 @@
error: Unexpected eof
--> $DIR/tests/test262-parser/fail/3d3e6ce2b81a224d.js:1:46
|
1 | [[[[[[[[[[[[[[[[[[[[{a=b}]]]]]]]]]]]]]]]]]]]]
| ^
error: Unexpected token
--> $DIR/tests/test262-parser/fail/3d3e6ce2b81a224d.js:1:22
|

View File

@ -1,3 +1,9 @@
error: Unexpected eof
--> $DIR/tests/test262-parser/fail/41895c8145489971.js:1:19
|
1 | `hello ${10 `test`
| ^
error: Expected RBrace
--> $DIR/tests/test262-parser/fail/41895c8145489971.js:1:18
|

View File

@ -1,3 +1,9 @@
error: Unexpected eof
--> $DIR/tests/test262-parser/fail/4e885526e8dfaa12.js:1:11
|
1 | f({x = 0})
| ^
error: Unexpected token
--> $DIR/tests/test262-parser/fail/4e885526e8dfaa12.js:1:4
|

View File

@ -1,3 +1,9 @@
error: Unexpected eof
--> $DIR/tests/test262-parser/fail/4ee7b10cd97f554c.js:1:3
|
1 | [,
| ^
error: Expected RBracket
--> $DIR/tests/test262-parser/fail/4ee7b10cd97f554c.js:1:2
|

View File

@ -1,3 +1,9 @@
error: Unexpected eof
--> $DIR/tests/test262-parser/fail/7187f0675eb38279.js:1:7
|
1 | return
| ^
error: Return statement is not allowed here
--> $DIR/tests/test262-parser/fail/7187f0675eb38279.js:1:1
|

View File

@ -1,3 +1,9 @@
error: Unexpected eof
--> $DIR/tests/test262-parser/fail/73d1b1b1bc1dabfb.js:1:6
|
1 | super
| ^
error: Unexpected token
--> $DIR/tests/test262-parser/fail/73d1b1b1bc1dabfb.js:1:1
|

View File

@ -1,3 +1,9 @@
error: Unexpected eof
--> $DIR/tests/test262-parser/fail/888d17b2ef3b2afc.js:1:10
|
1 | 1 + { t:t
| ^
error: Expected Comma
--> $DIR/tests/test262-parser/fail/888d17b2ef3b2afc.js:1:9
|

View File

@ -1,3 +1,9 @@
error: Unexpected eof
--> $DIR/tests/test262-parser/fail/8ba15f5246ca756c.js:1:10
|
1 | class A {
| ^
error: Expected RBrace
--> $DIR/tests/test262-parser/fail/8ba15f5246ca756c.js:1:9
|

View File

@ -1,3 +1,9 @@
error: Unexpected eof
--> $DIR/tests/test262-parser/fail/8c353ce78b905b58.js:1:5
|
1 | `${a
| ^
error: Expected RBrace
--> $DIR/tests/test262-parser/fail/8c353ce78b905b58.js:1:4
|

View File

@ -1,3 +1,9 @@
error: Unexpected eof
--> $DIR/tests/test262-parser/fail/a069c2ecbeb0f43a.js:1:37
|
1 | switch (cond) { case 10: let a = 20;
| ^
error: Expected RBrace
--> $DIR/tests/test262-parser/fail/a069c2ecbeb0f43a.js:1:36
|

View File

@ -1,3 +1,9 @@
error: Unexpected eof
--> $DIR/tests/test262-parser/fail/a9431906f263368d.js:1:10
|
1 | ({a = 0})
| ^
error: Unexpected token
--> $DIR/tests/test262-parser/fail/a9431906f263368d.js:1:3
|

View File

@ -1,3 +1,9 @@
error: Unexpected eof
--> $DIR/tests/test262-parser/fail/bcde05eea9466dfd.js:1:12
|
1 | [...{a=0},]
| ^
error: Unexpected token
--> $DIR/tests/test262-parser/fail/bcde05eea9466dfd.js:1:6
|

View File

@ -1,3 +1,9 @@
error: Unexpected eof
--> $DIR/tests/test262-parser/fail/c0ad1c20e662c8ed.js:1:14
|
1 | obj = {x = 0}
| ^
error: Unexpected token
--> $DIR/tests/test262-parser/fail/c0ad1c20e662c8ed.js:1:8
|

View File

@ -1,3 +1,9 @@
error: Unexpected eof
--> $DIR/tests/test262-parser/fail/d4e259842c4520e1.js:1:6
|
1 | 1 + (
| ^
error: Expected RParen
--> $DIR/tests/test262-parser/fail/d4e259842c4520e1.js:1:5
|

View File

@ -1,3 +1,9 @@
error: Unexpected eof
--> $DIR/tests/test262-parser/fail/dc5864c9096ad0a8.js:1:17
|
1 | [a, ...b, {c=0}]
| ^
error: Unexpected token
--> $DIR/tests/test262-parser/fail/dc5864c9096ad0a8.js:1:12
|

View File

@ -1,3 +1,9 @@
error: Unexpected eof
--> $DIR/tests/test262-parser/fail/e922f1c6f6e5fdef.module.js:1:24
|
1 | export default function
| ^
error: Expected LParen
--> $DIR/tests/test262-parser/fail/e922f1c6f6e5fdef.module.js:1:16
|

View File

@ -1,3 +1,9 @@
error: Unexpected eof
--> $DIR/tests/test262-parser/fail/f51aea0352bb03f3.js:1:4
|
1 | --1
| ^
error: Cannot assign to this
--> $DIR/tests/test262-parser/fail/f51aea0352bb03f3.js:1:3
|

View File

@ -1,3 +1,9 @@
error: Unexpected eof
--> $DIR/tests/test262-parser/fail/f6cc48c72caf2e32.js:1:4
|
1 | ++1
| ^
error: Cannot assign to this
--> $DIR/tests/test262-parser/fail/f6cc48c72caf2e32.js:1:3
|

View File

@ -283,13 +283,7 @@ where
(&*fm).into(),
));
match res {
Ok(res) => Ok(res),
Err(err) => {
err.emit();
Err(())
}
}
res
});
output

View File

@ -2,16 +2,20 @@
name = "swc_ecma_transforms"
version = "0.1.0"
authors = ["강동윤 <kdy1@outlook.kr>"]
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"
documentation = "https://swc-project.github.io/rustdoc/swc_ecma_transforms/"
description = "rust port of babel and closure compiler."
[dependencies]
swc_atoms = { path = "../../atoms" }
swc_common = { path = "../../common" }
swc_ecma_ast = { path = "../ast" }
swc_ecma_parser = { path = "../parser" }
swc_atoms = { version = "0.1", path ="../../atoms" }
swc_common = { version = "0.1", path ="../../common" }
swc_ecma_ast = { version = "0.1", path ="../ast" }
swc_ecma_parser = { version = "0.2", path ="../parser" }
slog = "2"
[dev-dependencies]
testing = { path = "../../testing" }
swc_ecma_codegen = { path = "../codegen" }
testing = { version = "0.1", path ="../../testing" }
swc_ecma_codegen = { version = "0.1", path ="../codegen" }
pretty_assertions = "0.5"
sourcemap = "2.2"

View File

@ -0,0 +1,59 @@
use ast::*;
use crate::{compat::helpers::Helpers, util::ExprFactory};
use std::sync::{atomic::Ordering, Arc};
use swc_common::{Fold, FoldWith};
/// `@babel/plugin-transform-instanceof`
///
///
///
/// # Example
///
/// ## In
///
/// ```js
/// foo instanceof Bar;
/// ```
///
/// ## Out
///
/// ```js
/// function _instanceof(left, right) {
/// if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
/// return right[Symbol.hasInstance](left);
/// } else {
/// return left instanceof right;
/// }
/// }
///
/// _instanceof(foo, Bar);
/// ```
pub struct InstanceOf {
pub helpers: Arc<Helpers>,
}
impl Fold<Expr> for InstanceOf {
fn fold(&mut self, expr: Expr) -> Expr {
let expr = expr.fold_children(self);
match expr {
Expr::Bin(BinExpr {
span,
left,
op: op!("instanceof"),
right,
}) => {
self.helpers.instance_of.store(true, Ordering::SeqCst);
let span = mark!(span);
Expr::Call(CallExpr {
span,
callee: quote_ident!(span, "_instanceof").as_callee(),
args: vec![left.as_arg(), right.as_arg()],
})
}
_ => expr,
}
}
}

View File

@ -1,6 +1,7 @@
pub use self::{
arrow::Arrow, classes::Classes, shorthand_property::Shorthand, spread::Spread,
sticky_regex::StickyRegex, template_literal::TemplateLiteral,
arrow::Arrow, classes::Classes, instanceof::InstanceOf, shorthand_property::Shorthand,
spread::Spread, sticky_regex::StickyRegex, template_literal::TemplateLiteral,
typeof_symbol::TypeOfSymbol,
};
use super::helpers::Helpers;
@ -10,13 +11,15 @@ use swc_common::Fold;
mod arrow;
mod classes;
mod instanceof;
mod shorthand_property;
mod spread;
mod sticky_regex;
mod template_literal;
mod typeof_symbol;
/// Compiles es2015 to es5.
pub fn es2015(helpers: Arc<Helpers>) -> impl Fold<Module> {
pub fn es2015(helpers: &Arc<Helpers>) -> impl Fold<Module> {
Classes {
helpers: helpers.clone(),
}
@ -25,4 +28,10 @@ pub fn es2015(helpers: Arc<Helpers>) -> impl Fold<Module> {
})
.then(StickyRegex)
.then(Shorthand)
.then(InstanceOf {
helpers: helpers.clone(),
})
.then(TypeOfSymbol {
helpers: helpers.clone(),
})
}

View File

@ -11,7 +11,7 @@ impl Fold<Expr> for TemplateLiteral {
match e {
Expr::Tpl(TplLit { .. }) => {
// TODO
unimplemented!()
unimplemented!("template literal")
}
_ => e,
}

View File

@ -0,0 +1,49 @@
use ast::*;
use crate::{compat::helpers::Helpers, util::ExprFactory};
use std::sync::{atomic::Ordering, Arc};
use swc_common::{Fold, FoldWith};
/// `@babel/plugin-transform-typeof-symbol`
///
/// # Example
/// ## In
///
/// ```js
/// typeof Symbol() === "symbol";
/// ```
///
/// ## Out
/// ```js
/// var _typeof = function (obj) {
/// return obj && obj.constructor === Symbol ? "symbol" : typeof obj;
/// };
///
/// _typeof(Symbol()) === "symbol";
/// ```
pub struct TypeOfSymbol {
pub helpers: Arc<Helpers>,
}
impl Fold<Expr> for TypeOfSymbol {
fn fold(&mut self, expr: Expr) -> Expr {
let expr = expr.fold_children(self);
match expr {
Expr::Unary(UnaryExpr {
span,
op: op!("typeof"),
arg,
}) => {
let span = mark!(span);
self.helpers.type_of.store(true, Ordering::SeqCst);
return Expr::Call(CallExpr {
span,
callee: quote_ident!(span, "_typeof").as_callee(),
args: vec![arg.as_arg()],
});
}
_ => expr,
}
}
}

View File

@ -0,0 +1,7 @@
function _instanceof(left, right) {
if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
return right[Symbol.hasInstance](left);
} else {
return left instanceof right;
}
}

View File

@ -0,0 +1,3 @@
var _typeof = function (obj) {
return obj && obj.constructor === Symbol ? "symbol" : typeof obj;
};

View File

@ -1,10 +1,7 @@
use ast::*;
use std::{
ops::BitOr,
sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
};
use swc_common::{
errors::{ColorConfig, Handler},
@ -29,23 +26,10 @@ pub struct Helpers {
pub create_class: AtomicBool,
/// `_get`
pub get: AtomicBool,
}
impl<'a> BitOr<&'a Helpers> for Helpers {
type Output = Self;
fn bitor(mut self, other: &Helpers) -> Self {
*self.extends.get_mut() |= other.extends.load(Ordering::SeqCst);
*self.to_consumable_array.get_mut() |= other.to_consumable_array.load(Ordering::SeqCst);
*self.class_call_check.get_mut() |= other.class_call_check.load(Ordering::SeqCst);
*self.inherits.get_mut() |= other.inherits.load(Ordering::SeqCst);
*self.possible_constructor_return.get_mut() |=
other.possible_constructor_return.load(Ordering::SeqCst);
*self.create_class.get_mut() |= other.create_class.load(Ordering::SeqCst);
*self.get.get_mut() |= other.get.load(Ordering::SeqCst);
self
}
/// _instanceof
pub instance_of: AtomicBool,
/// _typeof
pub type_of: AtomicBool,
}
pub struct InjectHelpers {
@ -76,46 +60,28 @@ impl InjectHelpers {
let mut stmts = Parser::new(session, SourceFileInput::from(&*fm))
.parse_script()
.map_err(|e| {
e.emit();
()
})
.unwrap();
buf.append(&mut stmts);
};
macro_rules! add {
($name:tt,$b:expr) => {
add($name, &self.helpers.extends, include_str!($name));
};
}
add(
"_extends.js",
&self.helpers.extends,
include_str!("_extends.js"),
);
add(
"_toConsumableArray.js",
&self.helpers.to_consumable_array,
include_str!("_toConsumableArray.js"),
);
add(
"_classCallCheck.js",
&self.helpers.class_call_check,
include_str!("_classCallCheck.js"),
);
add(
"_inherits.js",
&self.helpers.inherits,
include_str!("_inherits.js"),
);
add(
add!("_extends.js", &self.helpers.extends);
add!("_toConsumableArray.js", &self.helpers.to_consumable_array);
add!("_classCallCheck.js", &self.helpers.class_call_check);
add!("_inherits.js", &self.helpers.inherits);
add!(
"_possibleConstructorReturn.js",
&self.helpers.possible_constructor_return,
include_str!("_possibleConstructorReturn.js"),
&self.helpers.possible_constructor_return
);
add(
"_createClass.js",
&self.helpers.create_class,
include_str!("_createClass.js"),
);
add("_get.js", &self.helpers.get, include_str!("_get.js"));
add!("_createClass.js", &self.helpers.create_class);
add!("_get.js", &self.helpers.get);
add!("_instanceof.js", &self.helpers.instance_of);
add!("_typeof.js", &self.helpers.type_of);
buf
}

View File

@ -0,0 +1,135 @@
use ast::*;
use std::collections::HashMap;
use swc_atoms::JsWord;
use swc_common::{Fold, FoldWith};
pub struct InlineGlobals {
pub envs: HashMap<JsWord, Expr>,
pub globals: HashMap<JsWord, Expr>,
}
impl Fold<Expr> for InlineGlobals {
fn fold(&mut self, expr: Expr) -> Expr {
let expr = match expr {
// Don't recurese into member expression.
Expr::Member(..) => expr,
_ => expr.fold_children(self),
};
match expr {
Expr::Ident(Ident { ref sym, span }) => {
// It's ok because we don't recurse into member expressions.
if let Some(value) = self.globals.get(sym) {
return value.clone();
} else {
expr
}
}
Expr::Member(MemberExpr {
span,
obj:
ExprOrSuper::Expr(box Expr::Member(MemberExpr {
obj:
ExprOrSuper::Expr(box Expr::Ident(Ident {
sym: js_word!("process"),
..
})),
prop:
box Expr::Ident(Ident {
sym: js_word!("env"),
..
}),
span: _,
computed: _,
})),
prop,
computed: _,
}) => {
let prop = match *prop {
Expr::Ident(Ident { ref sym, .. }) => {
if let Some(env) = self.envs.get(sym) {
return env.clone();
}
return Expr::Lit(Lit::Str(Str {
value: js_word!(""),
span: mark!(span),
has_escape: false,
}));
}
_ => unimplemented!("node.env.NONE-IDENT"),
};
}
_ => expr,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn mk_map(values: &[(&str, &str)], is_env: bool) -> HashMap<JsWord, Expr> {
let mut m = HashMap::new();
crate::tests::Tester::run(|tester| {
for (k, v) in values {
let v = if is_env {
format!("'{}'", v)
} else {
(*v).into()
};
let mut v = tester.apply_transform(::testing::DropSpan, "global.js", &v)?;
assert_eq!(v.body.len(), 1);
let v = match v.body.pop().unwrap() {
ModuleItem::Stmt(Stmt::Expr(box expr)) => expr,
_ => unreachable!(),
};
m.insert((*k).into(), v);
}
Ok(())
});
m
}
fn envs(values: &[(&str, &str)]) -> HashMap<JsWord, Expr> {
mk_map(values, true)
}
fn globals(values: &[(&str, &str)]) -> HashMap<JsWord, Expr> {
mk_map(values, false)
}
test!(
InlineGlobals {
envs: envs(&[("NODE_ENV", "development")]),
globals: globals(&[]),
},
node_env,
r#"if (process.env.NODE_ENV === 'development') {}"#,
r#"if ('development' === 'development') {}"#
);
test!(
InlineGlobals {
envs: envs(&[]),
globals: globals(&[("__DEBUG__", "true")]),
},
inline_globals,
r#"if (__DEBUG__) {}"#,
r#"if (true) {}"#
);
test!(
InlineGlobals {
envs: envs(&[]),
globals: globals(&[("debug", "true")]),
},
non_global,
r#"if (foo.debug) {}"#,
r#"if (foo.debug) {}"#
);
}

View File

@ -23,7 +23,7 @@ extern crate sourcemap;
#[macro_use]
extern crate testing;
pub use self::simplify::simplifier;
pub use self::{inline_globals::InlineGlobals, simplify::simplifier};
#[cfg(test)]
#[macro_use]
@ -32,6 +32,7 @@ mod tests;
mod quote;
pub mod compat;
mod fixer;
mod inline_globals;
pub mod scope;
mod simplify;
pub mod util;

View File

@ -1,5 +1,5 @@
use swc_common::{Fold, FoldWith};
use ast::*;
use swc_common::{Fold, FoldWith};
pub trait FoldScope<T> {
/// `scope`: Scope which contains `node`.

View File

@ -41,8 +41,8 @@ impl<'a> Tester<'a> {
pub fn apply_transform<T: Fold<Module>>(
&mut self,
mut tr: T,
name: &'static str,
src: &'static str,
name: &str,
src: &str,
) -> Result<Module, ()> {
let fm = self
.cm
@ -57,10 +57,7 @@ impl<'a> Tester<'a> {
let module = {
let mut p = Parser::new(sess, SourceFileInput::from(&*fm));
p.parse_module().map_err(|err| {
err.emit();
()
})?
p.parse_module()?
};
// println!("parsed {} as a module\n{:?}", src, module);

View File

@ -3,11 +3,15 @@ name = "libswc"
version = "0.1.0"
authors = ["강동윤 <kdy1@outlook.kr>"]
edition = "2018"
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"
documentation = "https://swc-project.github.io/rustdoc/libswc/"
description = "Speedy web compiler: Make the web (development) faster"
[dependencies]
swc_atoms = { path = "../atoms" }
swc_common = { path = "../common" }
swc_ecmascript = { path = "../ecmascript" }
swc_atoms = { version = "0.1", path ="../atoms" }
swc_common = { version = "0.1", path ="../common" }
swc_ecmascript = { version = "0.1", path ="../ecmascript" }
rayon = "1.0.3"
slog = "2"
sourcemap = "2.2"

View File

@ -51,13 +51,7 @@ impl Compiler {
logger: &logger,
cfg: Default::default(),
};
let module = Parser::new(session, SourceFileInput::from(&*fm))
.parse_module()
.map_err(|e| {
e.emit();
()
});
module
Parser::new(session, SourceFileInput::from(&*fm)).parse_module()
}
}

View File

@ -2,12 +2,16 @@
name = "ast_node"
version = "0.1.0"
authors = ["강동윤 <kdy1@outlook.kr>"]
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"
documentation = "https://swc-project.github.io/rustdoc/ast_node/"
description = "Macros for ast nodes."
[lib]
proc-macro = true
[dependencies]
swc_macros_common = { path = "../common" }
swc_macros_common = { version = "0.1", path = "../common" }
pmutil = "0.2"
proc-macro2 = { version = "0.4.4", features = ["nightly"] }
quote = "0.6"
@ -19,4 +23,4 @@ features = ["derive", "fold", "parsing", "printing"]
[dev-dependencies]
swc_common = { path = "../../common" }
swc_common = { version = "0.1", path = "../../common" }

View File

@ -2,6 +2,10 @@
name = "swc_macros_common"
version = "0.1.0"
authors = ["강동윤 <kdy1@outlook.kr>"]
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"
documentation = "https://swc-project.github.io/rustdoc/swc_macros_common/"
description = "Common utilities for swc macros."
[dependencies]
pmutil = "0.2"

View File

@ -2,12 +2,16 @@
name = "enum_kind"
version = "0.1.0"
authors = ["강동윤 <kdy1@outlook.kr>"]
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"
documentation = "https://swc-project.github.io/rustdoc/enum_kind/"
description = "Easily manage values related to enum."
[lib]
proc-macro = true
[dependencies]
swc_macros_common = { path = "../common" }
swc_macros_common = { version = "0.1", path ="../common" }
pmutil = "0.2"
proc-macro2 = "0.4.4"

View File

@ -2,12 +2,16 @@
name = "string_enum"
version = "0.1.0"
authors = ["강동윤 <kdy1@outlook.kr>"]
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"
documentation = "https://swc-project.github.io/rustdoc/string_enum/"
description = "String based enum."
[lib]
proc-macro = true
[dependencies]
swc_macros_common = { path = "../common" }
swc_macros_common = { version = "0.1", path ="../common" }
pmutil = "0.2"
proc-macro2 = "0.4.4"
quote = "0.6.3"

View File

@ -114,7 +114,7 @@ fn js_pass(cm: Lrc<SourceMap>, matches: &ArgMatches) -> Box<Fold<Module>> {
let helpers = Arc::new(compat::helpers::Helpers::default());
let pass: Box<Fold<Module>> = box compat::es2016()
.then(compat::es2015(helpers.clone()))
.then(compat::es2015(&helpers))
.then(compat::es3())
.then(compat::helpers::InjectHelpers {
cm,

View File

@ -2,9 +2,13 @@
name = "testing"
version = "0.1.0"
authors = ["강동윤 <kdy1@outlook.kr>"]
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"
documentation = "https://swc-project.github.io/rustdoc/testing/"
description = "Testing utilities for the swc project."
[dependencies]
swc_common = { path = "../common" }
swc_common = { version = "0.1", path ="../common" }
slog = "2"
slog-envlogger = "2.1"
slog-term = "2.3"