- The parser now supports parsing optional patterns in .d.ts files (Closes #709)
 - The source map is handled properly (Closes #705, Closes #707)
This commit is contained in:
강동윤 2020-03-09 21:18:41 +09:00 committed by GitHub
parent ffbb5163aa
commit e448a8910c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
154 changed files with 1895 additions and 1037 deletions

View File

@ -1002,7 +1002,7 @@ impl SourceMap {
// mappings.sort_by_key(|v| v.0);
let mut cur_file: Option<Arc<SourceFile>> = None;
// let mut src_id = None;
let mut src_id;
let mut ch_start = 0;
let mut line_ch_start = 0;
@ -1021,11 +1021,11 @@ impl SourceMap {
Some(ref f) if f.start_pos <= pos && pos < f.end_pos => f,
_ => {
f = self.lookup_source_file(pos);
builder.add_source(&f.src);
src_id = builder.add_source(&f.name.to_string());
builder.set_source_contents(src_id, Some(&f.src));
cur_file = Some(f.clone());
ch_start = 0;
line_ch_start = 0;
// src_id = Some(builder.add_source(&f.src));
&f
}
};

View File

@ -1,6 +1,6 @@
[package]
name = "swc_ecma_ast"
version = "0.17.1"
version = "0.18.0"
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"

View File

@ -35,6 +35,10 @@ pub struct ArrayPat {
#[serde(rename = "elements")]
pub elems: Vec<Option<Pat>>,
/// Only in .d.ts file
#[serde(rename = "elements")]
pub optional: bool,
#[serde(default, rename = "typeAnnotation")]
pub type_ann: Option<TsTypeAnn>,
}
@ -47,6 +51,10 @@ pub struct ObjectPat {
#[serde(rename = "properties")]
pub props: Vec<ObjectPatProp>,
/// Only in .d.ts file
#[serde(rename = "elements")]
pub optional: bool,
#[serde(default, rename = "typeAnnotation")]
pub type_ann: Option<TsTypeAnn>,
}

View File

@ -13,11 +13,11 @@ bitflags = "1"
hashbrown = "0.6"
swc_atoms = { version = "0.2", path ="../../atoms" }
swc_common = { version = "0.5", path ="../../common" }
swc_ecma_ast = { version = "0.17.0", path ="../ast" }
swc_ecma_ast = { version = "0.18.0", path ="../ast" }
swc_ecma_codegen_macros = { version = "0.5", path ="./macros" }
sourcemap = "5"
num-bigint = { version = "0.2", features = ["serde"] }
swc_ecma_parser = { version = "0.20", path ="../parser" }
swc_ecma_parser = { version = "0.21", path ="../parser" }
[dev-dependencies]
testing = { version = "0.5", path ="../../testing" }

View File

@ -5,7 +5,7 @@ use swc_ecma_codegen_macros::emitter;
impl<'a> Emitter<'a> {
#[emitter]
pub fn emit_decl(&mut self, node: &Decl) -> Result {
fn emit_decl(&mut self, node: &Decl) -> Result {
match *node {
Decl::Class(ref n) => emit!(n),
Decl::Fn(ref n) => emit!(n),
@ -22,23 +22,35 @@ impl<'a> Emitter<'a> {
}
#[emitter]
pub fn emit_class_decl(&mut self, node: &ClassDecl) -> Result {
fn emit_class_decl(&mut self, node: &ClassDecl) -> Result {
self.emit_leading_comments_of_pos(node.span().lo())?;
if node.declare {
keyword!("declare");
space!();
}
for dec in &node.class.decorators {
emit!(dec);
}
keyword!("class");
space!();
emit!(node.ident);
emit!(node.class.type_params);
formatting_space!();
self.emit_class_trailing(&node.class)?;
}
#[emitter]
pub fn emit_fn_decl(&mut self, node: &FnDecl) -> Result {
fn emit_fn_decl(&mut self, node: &FnDecl) -> Result {
self.emit_leading_comments_of_pos(node.span().lo())?;
if node.declare {
keyword!("declare");
space!();
}
if node.function.is_async {
keyword!("async");
space!();
@ -56,9 +68,14 @@ impl<'a> Emitter<'a> {
}
#[emitter]
pub fn emit_var_decl(&mut self, node: &VarDecl) -> Result {
fn emit_var_decl(&mut self, node: &VarDecl) -> Result {
self.emit_leading_comments_of_pos(node.span.lo())?;
if node.declare {
keyword!("declare");
space!();
}
keyword!(node.kind.as_str());
space!();
@ -70,7 +87,7 @@ impl<'a> Emitter<'a> {
}
#[emitter]
pub fn emit_var_declator(&mut self, node: &VarDeclarator) -> Result {
fn emit_var_declarator(&mut self, node: &VarDeclarator) -> Result {
self.emit_leading_comments_of_pos(node.span().lo())?;
emit!(node.name);

View File

@ -93,6 +93,7 @@ mod tests {
}
#[test]
#[ignore]
fn class_expression() {
assert_min("(class {})", "(class{});");
assert_min("(class Foo {})", "(class Foo{});");

View File

@ -6,7 +6,7 @@ use swc_ecma_codegen_macros::emitter;
impl<'a> Emitter<'a> {
#[emitter]
pub fn emit_jsx_element(&mut self, node: &JSXElement) -> Result {
fn emit_jsx_element(&mut self, node: &JSXElement) -> Result {
emit!(node.opening);
self.emit_list(
node.span(),
@ -19,7 +19,7 @@ impl<'a> Emitter<'a> {
}
#[emitter]
pub fn emit_jsx_opening_element(&mut self, node: &JSXOpeningElement) -> Result {
fn emit_jsx_opening_element(&mut self, node: &JSXOpeningElement) -> Result {
punct!("<");
emit!(node.name);
@ -36,7 +36,7 @@ impl<'a> Emitter<'a> {
}
#[emitter]
pub fn emit_jsx_element_name(&mut self, node: &JSXElementName) -> Result {
fn emit_jsx_element_name(&mut self, node: &JSXElementName) -> Result {
match *node {
JSXElementName::Ident(ref n) => emit!(n),
JSXElementName::JSXMemberExpr(ref n) => emit!(n),
@ -45,7 +45,7 @@ impl<'a> Emitter<'a> {
}
#[emitter]
pub fn emit_jsx_attr(&mut self, node: &JSXAttr) -> Result {
fn emit_jsx_attr(&mut self, node: &JSXAttr) -> Result {
emit!(node.name);
if let Some(ref value) = node.value {
@ -55,7 +55,7 @@ impl<'a> Emitter<'a> {
}
#[emitter]
pub fn emit_jsx_attr_value(&mut self, node: &JSXAttrValue) -> Result {
fn emit_jsx_attr_value(&mut self, node: &JSXAttrValue) -> Result {
match *node {
JSXAttrValue::Lit(ref n) => emit!(n),
JSXAttrValue::JSXExprContainer(ref n) => emit!(n),
@ -65,7 +65,7 @@ impl<'a> Emitter<'a> {
}
#[emitter]
pub fn emit_jsx_attr_name(&mut self, node: &JSXAttrName) -> Result {
fn emit_jsx_attr_name(&mut self, node: &JSXAttrName) -> Result {
match *node {
JSXAttrName::Ident(ref n) => emit!(n),
JSXAttrName::JSXNamespacedName(ref n) => emit!(n),
@ -73,7 +73,7 @@ impl<'a> Emitter<'a> {
}
#[emitter]
pub fn emit_jsx_attr_or_spread(&mut self, node: &JSXAttrOrSpread) -> Result {
fn emit_jsx_attr_or_spread(&mut self, node: &JSXAttrOrSpread) -> Result {
match *node {
JSXAttrOrSpread::JSXAttr(ref n) => emit!(n),
JSXAttrOrSpread::SpreadElement(ref n) => emit!(n),
@ -81,7 +81,7 @@ impl<'a> Emitter<'a> {
}
#[emitter]
pub fn emit_jsx_element_child(&mut self, node: &JSXElementChild) -> Result {
fn emit_jsx_element_child(&mut self, node: &JSXElementChild) -> Result {
match *node {
JSXElementChild::JSXElement(ref n) => emit!(n),
JSXElementChild::JSXExprContainer(ref n) => emit!(n),
@ -92,7 +92,7 @@ impl<'a> Emitter<'a> {
}
#[emitter]
pub fn emit_jsx_spread_child(&mut self, node: &JSXSpreadChild) -> Result {
fn emit_jsx_spread_child(&mut self, node: &JSXSpreadChild) -> Result {
punct!("{");
punct!("...");
emit!(node.expr);
@ -100,14 +100,14 @@ impl<'a> Emitter<'a> {
}
#[emitter]
pub fn emit_jsx_expr_container(&mut self, node: &JSXExprContainer) -> Result {
fn emit_jsx_expr_container(&mut self, node: &JSXExprContainer) -> Result {
punct!("{");
emit!(node.expr);
punct!("}");
}
#[emitter]
pub fn emit_jsx_expr(&mut self, node: &JSXExpr) -> Result {
fn emit_jsx_expr(&mut self, node: &JSXExpr) -> Result {
match *node {
JSXExpr::Expr(ref n) => emit!(n),
JSXExpr::JSXEmptyExpr(ref n) => emit!(n),
@ -115,14 +115,14 @@ impl<'a> Emitter<'a> {
}
#[emitter]
pub fn emit_jsx_closing_element(&mut self, node: &JSXClosingElement) -> Result {
fn emit_jsx_closing_element(&mut self, node: &JSXClosingElement) -> Result {
punct!("</");
emit!(node.name);
punct!(">");
}
#[emitter]
pub fn emit_jsx_fragment(&mut self, node: &JSXFragment) -> Result {
fn emit_jsx_fragment(&mut self, node: &JSXFragment) -> Result {
emit!(node.opening);
self.emit_list(
@ -135,39 +135,39 @@ impl<'a> Emitter<'a> {
}
#[emitter]
pub fn emit_jsx_opening_fragment(&mut self, node: &JSXOpeningFragment) -> Result {
fn emit_jsx_opening_fragment(&mut self, node: &JSXOpeningFragment) -> Result {
punct!("<>")
}
#[emitter]
pub fn emit_jsx_closing_fragment(&mut self, node: &JSXClosingFragment) -> Result {
fn emit_jsx_closing_fragment(&mut self, node: &JSXClosingFragment) -> Result {
punct!("</>")
}
#[emitter]
pub fn emit_jsx_namespaced_name(&mut self, node: &JSXNamespacedName) -> Result {
fn emit_jsx_namespaced_name(&mut self, node: &JSXNamespacedName) -> Result {
emit!(node.ns);
punct!(":");
emit!(node.name);
}
#[emitter]
pub fn emit_jsx_empty_expr(&mut self, node: &JSXEmptyExpr) -> Result {}
fn emit_jsx_empty_expr(&mut self, node: &JSXEmptyExpr) -> Result {}
#[emitter]
pub fn emit_jsx_text(&mut self, node: &JSXText) -> Result {
fn emit_jsx_text(&mut self, node: &JSXText) -> Result {
self.emit_js_word(node.span(), &node.value)?;
}
#[emitter]
pub fn emit_jsx_member_expr(&mut self, node: &JSXMemberExpr) -> Result {
fn emit_jsx_member_expr(&mut self, node: &JSXMemberExpr) -> Result {
emit!(node.obj);
punct!(".");
emit!(node.prop);
}
#[emitter]
pub fn emit_jsx_object(&mut self, node: &JSXObject) -> Result {
fn emit_jsx_object(&mut self, node: &JSXObject) -> Result {
match *node {
JSXObject::Ident(ref n) => emit!(n),
JSXObject::JSXMemberExpr(ref n) => emit!(n),

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
[package]
name = "swc_ecma_parser"
version = "0.20.0"
version = "0.21.0"
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"
@ -18,7 +18,7 @@ verify = ["fold"]
[dependencies]
swc_atoms = { version = "0.2", path ="../../atoms" }
swc_common = { version = "0.5.0", path ="../../common" }
swc_ecma_ast = { version = "0.17.0", path ="../ast" }
swc_ecma_ast = { version = "0.18.0", path ="../ast" }
swc_ecma_parser_macros = { version = "0.4", path ="./macros" }
enum_kind = { version = "0.2", path ="../../macros/enum_kind" }
unicode-xid = "0.2"

View File

@ -54,6 +54,9 @@ where
T: Parse,
P: Parse + Token,
{
if t.is_empty() {
return Punctuated::new();
}
let parser = Punctuated::parse_separated_nonempty;
parser.parse2(t).expect("failed parse args")
}
@ -132,7 +135,11 @@ impl Fold for InjectSelf {
"smallvec" | "vec" | "unreachable" | "tok" | "op" | "js_word" => i,
"println" | "print" | "format" | "assert" | "assert_eq" | "assert_ne"
| "debug_assert" | "debug_assert_eq" | "debug_assert_ne" | "dbg" => {
let mut args: Punctuated<Expr, token::Comma> = parse_args(i.tokens);
let mut args: Punctuated<Expr, token::Comma> = parse_args(i.tokens.clone());
if &*name == "dbg" && i.tokens.is_empty() {
return Macro { ..i };
}
args = args
.into_pairs()
.map(|el| el.map_item(|expr| self.fold_expr(expr)))
@ -169,10 +176,11 @@ impl Fold for InjectSelf {
}
//TODO: Collect expect and give that list to unexpected
"assert_and_bump" | "bump" | "cur" | "cur_pos" | "eat" | "eof" | "eat_exact"
| "expect" | "expect_exact" | "into_spanned" | "is" | "is_exact" | "is_one_of"
| "peeked_is" | "peek" | "peek_ahead" | "last_pos" | "return_if_arrow" | "span"
| "syntax_error" | "make_error" | "emit_error" | "unexpected" | "store" => {
"trace_cur" | "assert_and_bump" | "bump" | "cur" | "cur_pos" | "eat" | "eof"
| "eat_exact" | "expect" | "expect_exact" | "into_spanned" | "is" | "is_exact"
| "is_one_of" | "peeked_is" | "peek" | "peek_ahead" | "last_pos"
| "return_if_arrow" | "span" | "syntax_error" | "make_error" | "emit_error"
| "unexpected" | "store" => {
let parser = match self.parser {
Some(ref s) => s.clone(),
_ => {

View File

@ -180,9 +180,11 @@ pub enum SyntaxError {
TS1048,
TS1056,
TS1085,
TS1089,
TS1092,
TS1096,
TS1098,
TS1100,
TS1102,
TS1105,
TS1107,
@ -202,6 +204,7 @@ pub enum SyntaxError {
TS1093,
TS1094,
TS1196,
TS1242,
TS2369,
TS2371,
TS2406,

View File

@ -295,6 +295,13 @@ impl Syntax {
_ => false,
}
}
pub fn dts(self) -> bool {
match self {
Syntax::Typescript(t) => t.dts,
_ => false,
}
}
}
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
@ -308,6 +315,10 @@ pub struct TsConfig {
#[serde(default)]
pub dynamic_import: bool,
/// `.d.ts`
#[serde(skip, default)]
pub dts: bool,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialOrd, Ord, PartialEq, Eq)]

View File

@ -335,7 +335,7 @@ impl<'a, I: Tokens> Parser<'a, I> {
is_optional,
is_async: false,
is_generator: false,
is_static: false,
static_token: None,
key,
kind: MethodKind::Method,
},
@ -376,6 +376,12 @@ impl<'a, I: Tokens> Parser<'a, I> {
) -> PResult<'a, ClassMember> {
let is_static = static_token.is_some();
let modifier = self.parse_ts_modifier(&["abstract", "readonly"])?;
let modifier_span = if let Some(..) = modifier {
Some(self.input.prev_span())
} else {
None
};
let (is_abstract, readonly) = match modifier {
Some("abstract") => (true, self.parse_ts_modifier(&["readonly"])?.is_some()),
Some("readonly") => (self.parse_ts_modifier(&["abstract"])?.is_some(), true),
@ -409,7 +415,7 @@ impl<'a, I: Tokens> Parser<'a, I> {
accessibility,
is_abstract,
is_optional: false,
is_static,
static_token,
key,
kind: MethodKind::Method,
},
@ -494,7 +500,14 @@ impl<'a, I: Tokens> Parser<'a, I> {
}
}
// TODO: check for duplicate constructors
if let Some(static_token) = static_token {
self.emit_err(static_token, SyntaxError::TS1089)
}
if let Some(span) = modifier_span {
self.emit_err(make_span(span), SyntaxError::TS1242);
}
return Ok(ClassMember::Constructor(Constructor {
span: span!(start),
accessibility,
@ -515,7 +528,7 @@ impl<'a, I: Tokens> Parser<'a, I> {
accessibility,
decorators,
is_abstract,
is_static,
static_token,
kind: MethodKind::Method,
key,
is_async: false,
@ -559,7 +572,7 @@ impl<'a, I: Tokens> Parser<'a, I> {
|p| p.parse_unique_formal_params(),
MakeMethodArgs {
start,
is_static,
static_token,
key,
is_abstract,
accessibility,
@ -607,7 +620,7 @@ impl<'a, I: Tokens> Parser<'a, I> {
is_generator: false,
is_optional,
accessibility,
is_static,
static_token,
key,
kind: MethodKind::Getter,
},
@ -636,7 +649,7 @@ impl<'a, I: Tokens> Parser<'a, I> {
is_async: false,
is_generator: false,
accessibility,
is_static,
static_token,
key,
kind: MethodKind::Setter,
},
@ -929,7 +942,7 @@ impl<'a, I: Tokens> Parser<'a, I> {
start,
accessibility,
is_abstract,
is_static,
static_token,
decorators,
is_optional,
key,
@ -941,6 +954,7 @@ impl<'a, I: Tokens> Parser<'a, I> {
where
F: FnOnce(&mut Self) -> PResult<'a, Vec<Pat>>,
{
let is_static = static_token.is_some();
let ctx = Context {
span_of_fn_name: Some(key.span()),
..self.ctx()
@ -1147,7 +1161,7 @@ struct MakeMethodArgs {
start: BytePos,
accessibility: Option<Accessibility>,
is_abstract: bool,
is_static: bool,
static_token: Option<Span>,
decorators: Vec<Decorator>,
is_optional: bool,
key: Either<PrivateName, PropName>,

View File

@ -12,6 +12,8 @@ mod verifier;
#[parser]
impl<'a, I: Tokens> Parser<'a, I> {
pub fn parse_expr(&mut self) -> PResult<'a, Box<Expr>> {
trace_cur!(parse_expr);
let expr = self.parse_assignment_expr()?;
let start = expr.span().lo();
@ -32,6 +34,8 @@ impl<'a, I: Tokens> Parser<'a, I> {
///`parseMaybeAssign` (overrided)
pub(super) fn parse_assignment_expr(&mut self) -> PResult<'a, Box<Expr>> {
trace_cur!(parse_assignment_expr);
if self.input.syntax().typescript() {
// Note: When the JSX plugin is on, type assertions (`<T> x`) aren't valid
// syntax.
@ -94,6 +98,8 @@ impl<'a, I: Tokens> Parser<'a, I> {
///
/// `parseMaybeAssign`
fn parse_assignment_expr_base(&mut self) -> PResult<'a, Box<Expr>> {
trace_cur!(parse_assignment_expr_base);
if self.ctx().in_generator && is!("yield") {
return self.parse_yield_expr();
}
@ -125,6 +131,8 @@ impl<'a, I: Tokens> Parser<'a, I> {
start: BytePos,
cond: Box<Expr>,
) -> PResult<'a, Box<Expr>> {
trace_cur!(finish_assignment_expr);
match cur!(false) {
Ok(&Token::AssignOp(op)) => {
let left = if op == AssignOpToken::Assign {
@ -137,6 +145,16 @@ impl<'a, I: Tokens> Parser<'a, I> {
if !cond.is_valid_simple_assignment_target(self.ctx().strict) {
self.emit_err(cond.span(), SyntaxError::NotSimpleAssign)
}
let is_eval_or_arguments = match *cond {
Expr::Ident(ref i) => {
i.sym == js_word!("eval") || i.sym == js_word!("arguments")
}
_ => false,
};
if self.input.syntax().typescript() && self.ctx().strict && is_eval_or_arguments
{
self.emit_err(cond.span(), SyntaxError::TS1100);
}
// TODO
PatOrExpr::Expr(cond)
@ -158,6 +176,8 @@ impl<'a, I: Tokens> Parser<'a, I> {
/// Spec: 'ConditionalExpression'
fn parse_cond_expr(&mut self) -> PResult<'a, Box<Expr>> {
trace_cur!(parse_cond_expr);
let start = cur_pos!();
let test = self.parse_bin_expr()?;
@ -191,6 +211,8 @@ impl<'a, I: Tokens> Parser<'a, I> {
/// Parse a primary expression or arrow function
#[allow(clippy::cognitive_complexity)]
pub(super) fn parse_primary_expr(&mut self) -> PResult<'a, Box<Expr>> {
trace_cur!(parse_primary_expr);
let _ = cur!(false);
let start = cur_pos!();
@ -327,6 +349,7 @@ impl<'a, I: Tokens> Parser<'a, I> {
let params = vec![arg];
expect!("=>");
let body = self.parse_fn_body(true, false)?;
return Ok(Box::new(Expr::Arrow(ArrowExpr {
span: span!(start),
body,
@ -360,6 +383,8 @@ impl<'a, I: Tokens> Parser<'a, I> {
}
fn parse_array_lit(&mut self) -> PResult<'a, Box<Expr>> {
trace_cur!(parse_array_lit);
let start = cur_pos!();
assert_and_bump!('[');
@ -410,6 +435,8 @@ impl<'a, I: Tokens> Parser<'a, I> {
/// `is_new_expr`: true iff we are parsing production 'NewExpression'.
fn parse_member_expr_or_new_expr(&mut self, is_new_expr: bool) -> PResult<'a, Box<Expr>> {
trace_cur!(parse_member_expr_or_new_expr);
let start = cur_pos!();
if eat!("new") {
let span_of_new = span!(start);
@ -482,11 +509,15 @@ impl<'a, I: Tokens> Parser<'a, I> {
/// Parse `NewExpresion`.
/// This includes `MemberExpression`.
pub(super) fn parse_new_expr(&mut self) -> PResult<'a, Box<Expr>> {
trace_cur!(parse_new_expr);
self.parse_member_expr_or_new_expr(true)
}
/// Parse `Arguments[Yield, Await]`
pub(super) fn parse_args(&mut self, is_dynamic_import: bool) -> PResult<'a, Vec<ExprOrSpread>> {
trace_cur!(parse_args);
let start = cur_pos!();
expect!('(');
@ -518,6 +549,8 @@ impl<'a, I: Tokens> Parser<'a, I> {
/// AssignmentExpression[+In, ?Yield, ?Await]
/// ...AssignmentExpression[+In, ?Yield, ?Await]
pub(super) fn parse_expr_or_spread(&mut self) -> PResult<'a, ExprOrSpread> {
trace_cur!(parse_expr_or_spread);
let start = cur_pos!();
if eat!("...") {
@ -537,6 +570,8 @@ impl<'a, I: Tokens> Parser<'a, I> {
can_be_arrow: bool,
async_span: Option<Span>,
) -> PResult<'a, Box<Expr>> {
trace_cur!(parse_paren_expr_or_arrow_fn);
let start = cur_pos!();
// At this point, we can't know if it's parenthesized
@ -605,7 +640,7 @@ impl<'a, I: Tokens> Parser<'a, I> {
.collect();
let body: BlockStmtOrExpr = self.parse_fn_body(async_span.is_some(), false)?;
return Ok(Box::new(Expr::Arrow(ArrowExpr {
let arrow_expr = ArrowExpr {
span: span!(start),
is_async: async_span.is_some(),
is_generator: false,
@ -613,7 +648,27 @@ impl<'a, I: Tokens> Parser<'a, I> {
body,
return_type,
type_params: None,
})));
};
match arrow_expr.body {
BlockStmtOrExpr::BlockStmt(..) => match cur!(false) {
Ok(&Token::BinOp(..)) => {
// ) is required
self.emit_err(self.input.cur_span(), SyntaxError::TS1005);
let errored_expr =
self.parse_bin_op_recursively(Box::new(arrow_expr.into()), 0)?;
if !is!(';') {
// ; is required
self.emit_err(self.input.cur_span(), SyntaxError::TS1005);
}
return Ok(errored_expr);
}
_ => {}
},
_ => {}
}
return Ok(Box::new(Expr::Arrow(arrow_expr)));
}
let expr_or_spreads = paren_items
@ -698,6 +753,8 @@ impl<'a, I: Tokens> Parser<'a, I> {
&mut self,
is_tagged: bool,
) -> PResult<'a, (Vec<Box<Expr>>, Vec<TplElement>)> {
trace_cur!(parse_tpl_elements);
let mut exprs = vec![];
let cur_elem = self.parse_tpl_element(is_tagged)?;
@ -722,6 +779,8 @@ impl<'a, I: Tokens> Parser<'a, I> {
type_params: Option<TsTypeParamInstantiation>,
) -> PResult<'a, TaggedTpl> {
let start = tag.span().lo();
trace_cur!(parse_tagged_tpl);
let start = cur_pos!();
assert_and_bump!('`');
@ -740,6 +799,7 @@ impl<'a, I: Tokens> Parser<'a, I> {
}
fn parse_tpl(&mut self) -> PResult<'a, Tpl> {
trace_cur!(parse_tpl);
let start = cur_pos!();
assert_and_bump!('`');
@ -1093,6 +1153,8 @@ impl<'a, I: Tokens> Parser<'a, I> {
#[allow(clippy::cognitive_complexity)]
pub(super) fn parse_args_or_pats(&mut self) -> PResult<'a, Vec<PatOrExprOrSpread>> {
trace_cur!(parse_args_or_pats);
expect!('(');
let mut first = true;
@ -1162,6 +1224,9 @@ impl<'a, I: Tokens> Parser<'a, I> {
if peeked_is!(',') || peeked_is!(':') || peeked_is!(')') || peeked_is!('=') {
assert_and_bump!('?');
let _ = cur!(false);
if arg.spread.is_some() {
self.emit_err(make_span(self.input.prev_span()), SyntaxError::TS1047);
}
match *arg.expr {
Expr::Ident(..) => {}
_ => {
@ -1320,6 +1385,7 @@ impl<'a, I: Tokens> Parser<'a, I> {
let body: BlockStmtOrExpr = self.parse_fn_body(false, false)?;
expect!(')');
let span = span!(start);
return Ok(vec![PatOrExprOrSpread::ExprOrSpread(ExprOrSpread {
expr: Box::new(
ArrowExpr {
@ -1476,6 +1542,10 @@ impl<'a, I: Tokens> Parser<'a, I> {
_ => false,
};
if self.ctx().strict && is_eval_or_arguments {
self.emit_err(expr.span(), SyntaxError::TS1100);
}
fn should_deny(e: &Expr, deny_call: bool) -> bool {
match e {
Expr::Lit(..) => false,

View File

@ -103,6 +103,7 @@ fn object_rest_pat() {
is_generator: false,
params: vec![Pat::Object(ObjectPat {
span,
optional: false,
props: vec![ObjectPatProp::Rest(RestPat {
span,
dot3_token: span,

View File

@ -288,6 +288,12 @@ macro_rules! return_if_arrow {
}};
}
macro_rules! trace_cur {
($p:expr, $name:ident) => {{
// println!("{}: {:?}", stringify!($name), cur!($p, false));
}};
}
/// This macro requires macro named 'last_pos' to be in scope.
macro_rules! span {
($p:expr, $start:expr) => {{

View File

@ -373,9 +373,12 @@ impl<'a, I: Tokens> ParseObject<'a, Pat> for Parser<'a, I> {
}
}
let optional = self.input.syntax().dts() && eat!('?');
Ok(Pat::Object(ObjectPat {
span,
props,
optional,
type_ann: None,
}))
}

View File

@ -111,10 +111,12 @@ impl<'a, I: Tokens> Parser<'a, I> {
}
expect!(']');
let optional = self.input.syntax().dts() && eat!('?');
Ok(Pat::Array(ArrayPat {
span: span!(start),
elems,
optional,
type_ann: None,
}))
}
@ -146,7 +148,7 @@ impl<'a, I: Tokens> Parser<'a, I> {
let pat_start = cur_pos!();
let mut pat = self.parse_binding_element()?;
// let mut opt = false;
let mut opt = false;
if self.input.syntax().typescript() {
if eat!('?') {
@ -155,7 +157,7 @@ impl<'a, I: Tokens> Parser<'a, I> {
ref mut optional, ..
}) => {
*optional = true;
// opt = true;
opt = true;
}
_ => syntax_error!(
make_span(self.input.prev_span()),
@ -202,10 +204,10 @@ impl<'a, I: Tokens> Parser<'a, I> {
}
let pat = if eat!('=') {
// // `=` cannot follow optional parameter.
// if opt {
// self.emit_err(pat.span(), SyntaxError::TS1015);
// }
// `=` cannot follow optional parameter.
if opt {
self.emit_err(pat.span(), SyntaxError::TS1015);
}
let right = self.parse_assignment_expr()?;
if self.ctx().in_declare {
@ -442,6 +444,9 @@ impl<'a, I: Tokens> Parser<'a, I> {
pat_ty: PatType,
expr: Box<Expr>,
) -> PResult<'a, Pat> {
// In dts, we do not reparse.
debug_assert!(!self.input.syntax().dts());
let span = expr.span();
if pat_ty == PatType::AssignPat {
@ -578,6 +583,7 @@ impl<'a, I: Tokens> Parser<'a, I> {
}
})
.collect::<PResult<'a, _>>()?,
optional: false,
type_ann: None,
}))
}
@ -589,6 +595,7 @@ impl<'a, I: Tokens> Parser<'a, I> {
return Ok(Pat::Array(ArrayPat {
span,
elems: vec![],
optional: false,
type_ann: None,
}));
}
@ -657,6 +664,7 @@ impl<'a, I: Tokens> Parser<'a, I> {
Ok(Pat::Array(ArrayPat {
span,
elems: params,
optional: false,
type_ann: None,
}))
}
@ -763,15 +771,18 @@ mod tests {
array_pat("[a, [b], [c]]"),
Pat::Array(ArrayPat {
span,
optional: false,
elems: vec![
Some(Pat::Ident(ident("a"))),
Some(Pat::Array(ArrayPat {
span,
optional: false,
elems: vec![Some(Pat::Ident(ident("b")))],
type_ann: None
})),
Some(Pat::Array(ArrayPat {
span,
optional: false,
elems: vec![Some(Pat::Ident(ident("c")))],
type_ann: None
}))
@ -787,16 +798,19 @@ mod tests {
array_pat("[, a, [b], [c]]"),
Pat::Array(ArrayPat {
span,
optional: false,
elems: vec![
None,
Some(Pat::Ident(ident("a"))),
Some(Pat::Array(ArrayPat {
span,
optional: false,
elems: vec![Some(Pat::Ident(ident("b")))],
type_ann: None
})),
Some(Pat::Array(ArrayPat {
span,
optional: false,
elems: vec![Some(Pat::Ident(ident("c")))],
type_ann: None
}))
@ -812,16 +826,19 @@ mod tests {
array_pat("[a, , [b], [c]]"),
Pat::Array(ArrayPat {
span,
optional: false,
elems: vec![
Some(Pat::Ident(ident("a"))),
None,
Some(Pat::Array(ArrayPat {
span,
optional: false,
elems: vec![Some(Pat::Ident(ident("b")))],
type_ann: None
})),
Some(Pat::Array(ArrayPat {
span,
optional: false,
elems: vec![Some(Pat::Ident(ident("c")))],
type_ann: None
}))

View File

@ -105,6 +105,9 @@ impl<'a, I: Tokens> Parser<'a, I> {
let span = span!(start);
return Ok(Stmt::Expr(ExprStmt { span, expr }));
}
trace_cur!(parse_stmt_internal);
let start = cur_pos!();
if self.input.syntax().typescript() && is!("const") && peeked_is!("enum") {
assert_and_bump!("const");
@ -324,7 +327,7 @@ impl<'a, I: Tokens> Parser<'a, I> {
if self.syntax().typescript() {
match *expr {
Expr::Ident(ref i) => match i.sym {
js_word!("public") | js_word!("static") => {
js_word!("public") | js_word!("static") | js_word!("abstract") => {
if eat!("interface") {
self.emit_err(i.span, SyntaxError::TS2427);
return self
@ -370,7 +373,20 @@ impl<'a, I: Tokens> Parser<'a, I> {
expect!('(');
let test = self.include_in_expr(true).parse_expr()?;
expect!(')');
if !eat!(')') {
self.emit_err(self.input.cur_span(), SyntaxError::TS1005);
let span = span!(start);
return Ok(Stmt::If(IfStmt {
span,
test,
cons: Box::new(Stmt::Expr(ExprStmt {
span,
expr: Box::new(Expr::Invalid(Invalid { span })),
})),
alt: Default::default(),
}));
}
let cons = {
// Annex B
@ -1173,6 +1189,7 @@ mod tests {
span,
param: Pat::Object(ObjectPat {
span,
optional: false,
props: vec![ObjectPatProp::Rest(RestPat {
span,
dot3_token: span,

View File

@ -275,6 +275,10 @@ impl<'a, I: Tokens> Parser<'a, I> {
}
return Ok(class.into());
}
if is!("abstract") && peeked_is!("interface") {
self.emit_err(self.input.cur_span(), SyntaxError::TS1242);
assert_and_bump!("abstract");
}
if is!("interface") {
let interface_start = cur_pos!();

View File

@ -2315,3 +2315,80 @@ fn make_decl_declare(mut decl: Decl) -> Decl {
decl
}
#[cfg(test)]
mod tests {
use crate::{test_parser, Syntax};
use swc_common::DUMMY_SP;
use swc_ecma_ast::*;
use testing::assert_eq_ignore_span;
#[test]
fn issue_708_1() {
let actual = test_parser(
"type test = -1;",
Syntax::Typescript(Default::default()),
|p| p.parse_module().map_err(|mut e| e.emit()),
);
let expected = Module {
span: DUMMY_SP,
shebang: None,
body: {
let first = ModuleItem::Stmt(Stmt::Decl(Decl::TsTypeAlias(TsTypeAliasDecl {
span: DUMMY_SP,
declare: false,
id: Ident::new("test".into(), DUMMY_SP),
type_params: None,
type_ann: box TsType::TsLitType(TsLitType {
span: DUMMY_SP,
lit: TsLit::Number(Number {
span: DUMMY_SP,
value: -1.0,
}),
}),
})));
vec![first]
},
};
assert_eq_ignore_span!(actual, expected);
}
#[test]
fn issue_708_2() {
let actual = test_parser(
"const t = -1;",
Syntax::Typescript(Default::default()),
|p| p.parse_module().map_err(|mut e| e.emit()),
);
let expected = Module {
span: DUMMY_SP,
shebang: None,
body: {
let second = ModuleItem::Stmt(Stmt::Decl(Decl::Var(VarDecl {
span: DUMMY_SP,
kind: VarDeclKind::Const,
declare: false,
decls: vec![VarDeclarator {
span: DUMMY_SP,
name: Pat::Ident(Ident::new("t".into(), DUMMY_SP)),
init: Some(box Expr::Unary(UnaryExpr {
span: DUMMY_SP,
op: op!(unary, "-"),
arg: box Expr::Lit(Lit::Num(Number {
span: DUMMY_SP,
value: 1.0,
})),
})),
definite: false,
}],
})));
vec![second]
},
};
assert_eq_ignore_span!(actual, expected);
}
}

View File

@ -24,6 +24,9 @@ const IGNORED_PASS_TESTS: &[&str] = &[
"431ecef8c85d4d24.js",
"8386fbff927a9e0e.js",
"5654d4106d7025c2.js",
// Static constructor
"dcc5609dcc043200.js",
"88d42455ac933ef5.js",
// Wrong tests (variable name or value is different)
"0339fa95c78c11bd.js",
"0426f15dac46e92d.js",

View File

@ -0,0 +1,6 @@
error: TS1047
--> $DIR/tests/typescript-errors/arrow-function/async-rest-optional-parameter/input.ts:1:14
|
1 | async(...args?: any[]) : any => {}
| ^

View File

@ -0,0 +1,6 @@
error: TS1015
--> $DIR/tests/typescript-errors/class/parameter-properties/input.ts:10:16
|
10 | public y?: number = 0) {}
| ^^^^^^^^^^

View File

@ -154,6 +154,7 @@ where
let lexer = Lexer::new(
Session { handler: &handler },
Syntax::Typescript(TsConfig {
dts: fname.ends_with(".d.ts"),
tsx: fname.contains("tsx"),
dynamic_import: true,
decorators: true,

View File

@ -1,107 +0,0 @@
{
"type": "Module",
"span": {
"start": 0,
"end": 34,
"ctxt": 0
},
"body": [
{
"type": "ExpressionStatement",
"span": {
"start": 0,
"end": 34,
"ctxt": 0
},
"expression": {
"type": "ArrowFunctionExpression",
"span": {
"start": 5,
"end": 34,
"ctxt": 0
},
"params": [
{
"type": "RestElement",
"span": {
"start": 6,
"end": 21,
"ctxt": 0
},
"rest": {
"start": 6,
"end": 9,
"ctxt": 0
},
"argument": {
"type": "Identifier",
"span": {
"start": 9,
"end": 13,
"ctxt": 0
},
"value": "args",
"typeAnnotation": null,
"optional": true
},
"typeAnnotation": {
"type": "TsTypeAnnotation",
"span": {
"start": 14,
"end": 21,
"ctxt": 0
},
"typeAnnotation": {
"type": "TsArrayType",
"span": {
"start": 16,
"end": 21,
"ctxt": 0
},
"elemType": {
"type": "TsKeywordType",
"span": {
"start": 16,
"end": 19,
"ctxt": 0
},
"kind": "any"
}
}
}
}
],
"body": {
"type": "BlockStatement",
"span": {
"start": 32,
"end": 34,
"ctxt": 0
},
"stmts": []
},
"async": true,
"generator": false,
"typeParameters": null,
"returnType": {
"type": "TsTypeAnnotation",
"span": {
"start": 23,
"end": 28,
"ctxt": 0
},
"typeAnnotation": {
"type": "TsKeywordType",
"span": {
"start": 25,
"end": 28,
"ctxt": 0
},
"kind": "any"
}
}
}
}
],
"interpreter": null
}

View File

@ -58,6 +58,7 @@
}
}
],
"elements": false,
"typeAnnotation": null
}
],

View File

@ -21,7 +21,7 @@
},
"declare": false,
"span": {
"start": 0,
"start": 5,
"end": 196,
"ctxt": 0
},

View File

@ -1,309 +0,0 @@
{
"type": "Module",
"span": {
"start": 0,
"end": 257,
"ctxt": 0
},
"body": [
{
"type": "ClassDeclaration",
"identifier": {
"type": "Identifier",
"span": {
"start": 6,
"end": 7,
"ctxt": 0
},
"value": "C",
"typeAnnotation": null,
"optional": false
},
"declare": false,
"span": {
"start": 0,
"end": 257,
"ctxt": 0
},
"decorators": [],
"body": [
{
"type": "Constructor",
"span": {
"start": 14,
"end": 255,
"ctxt": 0
},
"key": {
"type": "Identifier",
"span": {
"start": 14,
"end": 25,
"ctxt": 0
},
"value": "constructor",
"typeAnnotation": null,
"optional": false
},
"params": [
{
"type": "TsParameterProperty",
"span": {
"start": 35,
"end": 45,
"ctxt": 0
},
"decorators": [],
"accessibility": null,
"readonly": true,
"param": {
"type": "Identifier",
"span": {
"start": 44,
"end": 45,
"ctxt": 0
},
"value": "r",
"typeAnnotation": null,
"optional": false
}
},
{
"type": "TsParameterProperty",
"span": {
"start": 55,
"end": 72,
"ctxt": 0
},
"decorators": [],
"accessibility": "public",
"readonly": false,
"param": {
"type": "Identifier",
"span": {
"start": 62,
"end": 72,
"ctxt": 0
},
"value": "pu",
"typeAnnotation": {
"type": "TsTypeAnnotation",
"span": {
"start": 64,
"end": 72,
"ctxt": 0
},
"typeAnnotation": {
"type": "TsKeywordType",
"span": {
"start": 66,
"end": 72,
"ctxt": 0
},
"kind": "number"
}
},
"optional": false
}
},
{
"type": "TsParameterProperty",
"span": {
"start": 82,
"end": 95,
"ctxt": 0
},
"decorators": [],
"accessibility": "protected",
"readonly": false,
"param": {
"type": "Identifier",
"span": {
"start": 92,
"end": 94,
"ctxt": 0
},
"value": "po",
"typeAnnotation": null,
"optional": true
}
},
{
"type": "TsParameterProperty",
"span": {
"start": 105,
"end": 124,
"ctxt": 0
},
"decorators": [],
"accessibility": "private",
"readonly": false,
"param": {
"type": "Identifier",
"span": {
"start": 113,
"end": 124,
"ctxt": 0
},
"value": "pi",
"typeAnnotation": {
"type": "TsTypeAnnotation",
"span": {
"start": 116,
"end": 124,
"ctxt": 0
},
"typeAnnotation": {
"type": "TsKeywordType",
"span": {
"start": 118,
"end": 124,
"ctxt": 0
},
"kind": "number"
}
},
"optional": true
}
},
{
"type": "TsParameterProperty",
"span": {
"start": 134,
"end": 153,
"ctxt": 0
},
"decorators": [],
"accessibility": "public",
"readonly": true,
"param": {
"type": "Identifier",
"span": {
"start": 150,
"end": 153,
"ctxt": 0
},
"value": "pur",
"typeAnnotation": null,
"optional": false
}
},
{
"type": "TsParameterProperty",
"span": {
"start": 206,
"end": 220,
"ctxt": 0
},
"decorators": [],
"accessibility": null,
"readonly": true,
"param": {
"type": "AssignmentPattern",
"span": {
"start": 215,
"end": 220,
"ctxt": 0
},
"left": {
"type": "Identifier",
"span": {
"start": 215,
"end": 216,
"ctxt": 0
},
"value": "x",
"typeAnnotation": null,
"optional": false
},
"right": {
"type": "NumericLiteral",
"span": {
"start": 219,
"end": 220,
"ctxt": 0
},
"value": 0.0
},
"typeAnnotation": null
}
},
{
"type": "TsParameterProperty",
"span": {
"start": 230,
"end": 251,
"ctxt": 0
},
"decorators": [],
"accessibility": "public",
"readonly": false,
"param": {
"type": "AssignmentPattern",
"span": {
"start": 237,
"end": 251,
"ctxt": 0
},
"left": {
"type": "Identifier",
"span": {
"start": 237,
"end": 247,
"ctxt": 0
},
"value": "y",
"typeAnnotation": {
"type": "TsTypeAnnotation",
"span": {
"start": 239,
"end": 247,
"ctxt": 0
},
"typeAnnotation": {
"type": "TsKeywordType",
"span": {
"start": 241,
"end": 247,
"ctxt": 0
},
"kind": "number"
}
},
"optional": true
},
"right": {
"type": "NumericLiteral",
"span": {
"start": 250,
"end": 251,
"ctxt": 0
},
"value": 0.0
},
"typeAnnotation": null
}
}
],
"body": {
"type": "BlockStatement",
"span": {
"start": 253,
"end": 255,
"ctxt": 0
},
"stmts": []
},
"accessibility": null,
"isOptional": false
}
],
"superClass": null,
"isAbstract": false,
"typeParams": null,
"superTypeParams": null,
"implements": []
}
],
"interpreter": null
}

View File

@ -0,0 +1,13 @@
declare namespace __event {
export class EventInit {
constructor({
bubbles,
cancelable,
composed
}?: {
bubbles?: boolean | undefined;
cancelable?: boolean | undefined;
composed?: boolean | undefined;
});
}
}

View File

@ -0,0 +1,374 @@
{
"type": "Module",
"span": {
"start": 0,
"end": 359,
"ctxt": 0
},
"body": [
{
"type": "TsModuleDeclaration",
"span": {
"start": 0,
"end": 359,
"ctxt": 0
},
"declare": true,
"global": false,
"id": {
"type": "Identifier",
"span": {
"start": 18,
"end": 25,
"ctxt": 0
},
"value": "__event",
"typeAnnotation": null,
"optional": false
},
"body": {
"type": "TsModuleBlock",
"span": {
"start": 26,
"end": 359,
"ctxt": 0
},
"body": [
{
"type": "ExportDeclaration",
"span": {
"start": 32,
"end": 357,
"ctxt": 0
},
"declaration": {
"type": "ClassDeclaration",
"identifier": {
"type": "Identifier",
"span": {
"start": 45,
"end": 54,
"ctxt": 0
},
"value": "EventInit",
"typeAnnotation": null,
"optional": false
},
"declare": false,
"span": {
"start": 39,
"end": 357,
"ctxt": 0
},
"decorators": [],
"body": [
{
"type": "Constructor",
"span": {
"start": 65,
"end": 351,
"ctxt": 0
},
"key": {
"type": "Identifier",
"span": {
"start": 65,
"end": 76,
"ctxt": 0
},
"value": "constructor",
"typeAnnotation": null,
"optional": false
},
"params": [
{
"type": "ObjectPattern",
"span": {
"start": 77,
"end": 349,
"ctxt": 0
},
"properties": [
{
"type": "AssignmentPatternProperty",
"span": {
"start": 103,
"end": 110,
"ctxt": 0
},
"key": {
"type": "Identifier",
"span": {
"start": 103,
"end": 110,
"ctxt": 0
},
"value": "bubbles",
"typeAnnotation": null,
"optional": false
},
"value": null
},
{
"type": "AssignmentPatternProperty",
"span": {
"start": 136,
"end": 146,
"ctxt": 0
},
"key": {
"type": "Identifier",
"span": {
"start": 136,
"end": 146,
"ctxt": 0
},
"value": "cancelable",
"typeAnnotation": null,
"optional": false
},
"value": null
},
{
"type": "AssignmentPatternProperty",
"span": {
"start": 172,
"end": 180,
"ctxt": 0
},
"key": {
"type": "Identifier",
"span": {
"start": 172,
"end": 180,
"ctxt": 0
},
"value": "composed",
"typeAnnotation": null,
"optional": false
},
"value": null
}
],
"elements": true,
"typeAnnotation": {
"type": "TsTypeAnnotation",
"span": {
"start": 203,
"end": 349,
"ctxt": 0
},
"typeAnnotation": {
"type": "TsTypeLiteral",
"span": {
"start": 205,
"end": 349,
"ctxt": 0
},
"members": [
{
"type": "TsPropertySignature",
"span": {
"start": 219,
"end": 249,
"ctxt": 0
},
"readonly": false,
"key": {
"type": "Identifier",
"span": {
"start": 219,
"end": 226,
"ctxt": 0
},
"value": "bubbles",
"typeAnnotation": null,
"optional": false
},
"computed": false,
"optional": true,
"init": null,
"params": [],
"typeAnnotation": {
"type": "TsTypeAnnotation",
"span": {
"start": 227,
"end": 248,
"ctxt": 0
},
"typeAnnotation": {
"type": "TsUnionType",
"span": {
"start": 229,
"end": 248,
"ctxt": 0
},
"types": [
{
"type": "TsKeywordType",
"span": {
"start": 229,
"end": 236,
"ctxt": 0
},
"kind": "boolean"
},
{
"type": "TsKeywordType",
"span": {
"start": 239,
"end": 248,
"ctxt": 0
},
"kind": "undefined"
}
]
}
},
"typeParams": null
},
{
"type": "TsPropertySignature",
"span": {
"start": 262,
"end": 295,
"ctxt": 0
},
"readonly": false,
"key": {
"type": "Identifier",
"span": {
"start": 262,
"end": 272,
"ctxt": 0
},
"value": "cancelable",
"typeAnnotation": null,
"optional": false
},
"computed": false,
"optional": true,
"init": null,
"params": [],
"typeAnnotation": {
"type": "TsTypeAnnotation",
"span": {
"start": 273,
"end": 294,
"ctxt": 0
},
"typeAnnotation": {
"type": "TsUnionType",
"span": {
"start": 275,
"end": 294,
"ctxt": 0
},
"types": [
{
"type": "TsKeywordType",
"span": {
"start": 275,
"end": 282,
"ctxt": 0
},
"kind": "boolean"
},
{
"type": "TsKeywordType",
"span": {
"start": 285,
"end": 294,
"ctxt": 0
},
"kind": "undefined"
}
]
}
},
"typeParams": null
},
{
"type": "TsPropertySignature",
"span": {
"start": 308,
"end": 339,
"ctxt": 0
},
"readonly": false,
"key": {
"type": "Identifier",
"span": {
"start": 308,
"end": 316,
"ctxt": 0
},
"value": "composed",
"typeAnnotation": null,
"optional": false
},
"computed": false,
"optional": true,
"init": null,
"params": [],
"typeAnnotation": {
"type": "TsTypeAnnotation",
"span": {
"start": 317,
"end": 338,
"ctxt": 0
},
"typeAnnotation": {
"type": "TsUnionType",
"span": {
"start": 319,
"end": 338,
"ctxt": 0
},
"types": [
{
"type": "TsKeywordType",
"span": {
"start": 319,
"end": 326,
"ctxt": 0
},
"kind": "boolean"
},
{
"type": "TsKeywordType",
"span": {
"start": 329,
"end": 338,
"ctxt": 0
},
"kind": "undefined"
}
]
}
},
"typeParams": null
}
]
}
}
}
],
"body": null,
"accessibility": null,
"isOptional": false
}
],
"superClass": null,
"isAbstract": false,
"typeParams": null,
"superTypeParams": null,
"implements": []
}
}
]
}
}
],
"interpreter": null
}

View File

@ -72,6 +72,7 @@
"value": null
}
],
"elements": false,
"typeAnnotation": {
"type": "TsTypeAnnotation",
"span": {

View File

@ -21,7 +21,7 @@
},
"declare": false,
"span": {
"start": 0,
"start": 21,
"end": 34,
"ctxt": 0
},

View File

@ -63,6 +63,7 @@
"value": null
}
],
"elements": false,
"typeAnnotation": {
"type": "TsTypeAnnotation",
"span": {

View File

@ -23,7 +23,7 @@
"callee": {
"type": "TaggedTemplateExpression",
"span": {
"start": 4,
"start": 9,
"end": 11,
"ctxt": 0
},

View File

@ -16,7 +16,7 @@
"expression": {
"type": "TaggedTemplateExpression",
"span": {
"start": 0,
"start": 4,
"end": 6,
"ctxt": 0
},

View File

@ -509,13 +509,12 @@ impl Query {
.output()
.expect("failed to collect output");
if !output.status.success() {
println!(
"{}\n{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr),
);
if !output.status.success() {
println!("query.js: Status {:?}", output.status,);
return Err(());
}

View File

@ -11,9 +11,9 @@ edition = "2018"
[dependencies]
swc_atoms = { version = "0.2.0", path ="../../atoms" }
swc_common = { version = "0.5.0", path ="../../common" }
swc_ecma_ast = { version = "0.17.0", path ="../ast" }
swc_ecma_ast = { version = "0.18.0", path ="../ast" }
swc_ecma_utils = { version = "0.4.0", path ="../utils" }
swc_ecma_parser = { version = "0.20", path ="../parser", features = ["verify"] }
swc_ecma_parser = { version = "0.21", path ="../parser", features = ["verify"] }
dashmap = "=3.5.1"
either = "1.5"
fxhash = "0.2"

View File

@ -1,11 +1,10 @@
use crate::{pass::Pass, util::undefined};
use smallvec::SmallVec;
use std::{iter::once, mem::replace};
use std::mem::replace;
use swc_common::{util::map::Map, Fold, FoldWith, Spanned, Visit, VisitWith, DUMMY_SP};
use swc_ecma_ast::*;
use swc_ecma_utils::{
contains_this_expr, find_ids, ident::IdentLike, prepend, var::VarCollector, ExprFactory, Id,
StmtLike,
find_ids, ident::IdentLike, prepend, var::VarCollector, ExprFactory, Id, StmtLike,
};
///
@ -119,7 +118,6 @@ impl BlockScoping {
}
let var_name = private_ident!("_loop");
let uses_this = contains_this_expr(&body);
self.vars.push(VarDeclarator {
span: DUMMY_SP,
@ -154,24 +152,7 @@ impl BlockScoping {
definite: false,
});
return if uses_this {
CallExpr {
span: DUMMY_SP,
callee: var_name.member(quote_ident!("call")).as_callee(),
args: once(ExprOrSpread {
spread: None,
expr: box Expr::This(ThisExpr { span: DUMMY_SP }),
})
.chain(args.into_iter().map(|i| ExprOrSpread {
spread: None,
expr: box Expr::Ident(Ident::new(i.0, DUMMY_SP.with_ctxt(i.1))),
}))
.collect(),
type_args: None,
}
.into_stmt()
} else {
CallExpr {
return CallExpr {
span: DUMMY_SP,
callee: var_name.as_callee(),
args: args
@ -183,8 +164,7 @@ impl BlockScoping {
.collect(),
type_args: None,
}
.into_stmt()
};
.into_stmt();
}
body
@ -786,90 +766,7 @@ foo();"
};
var vars = [];
var elem = null, name, val;
for(var i = 0; i < this.elements.length; i++)_loop.call(this, i);
return vars;
};"
);
test!(
::swc_ecma_parser::Syntax::default(),
|_| block_scoping(),
issue_698,
"module.exports = function(values) {
var vars = [];
var elem = null, name, val;
for (var i = 0; i < this.elements.length; i++) {
elem = this.elements[i];
name = elem.name;
if (!name) continue;
val = values[name];
if (val == null) val = '';
switch (elem.type) {
case 'submit':
break;
case 'radio':
case 'checkbox':
elem.checked = val.some(function(str) {
return str.toString() == elem.value;
});
break;
case 'select-multiple':
elem.fill(val);
break;
case 'textarea':
elem.innerText = val;
break;
case 'hidden':
break;
default:
if (elem.fill) {
elem.fill(val);
} else {
elem.value = val;
}
break;
}
}
return vars;
};
",
"module.exports = function(values) {
var _loop = function(i) {
elem = this.elements[i];
name = elem.name;
if (!name) return;
val = values[name];
if (val == null) val = '';
switch(elem.type){
case 'submit':
break;
case 'radio':
case 'checkbox':
elem.checked = val.some(function(str) {
return str.toString() == elem.value;
});
break;
case 'select-multiple':
elem.fill(val);
break;
case 'textarea':
elem.innerText = val;
break;
case 'hidden':
break;
default:
if (elem.fill) {
elem.fill(val);
} else {
elem.value = val;
}
break;
}
};
var vars = [];
var elem = null, name, val;
for(var i = 0; i < this.elements.length; i++)_loop.call(this, i);
for(var i = 0; i < this.elements.length; i++)_loop(i);
return vars;
};"
);

View File

@ -707,6 +707,7 @@ impl RestFolder {
span,
props,
type_ann,
..
} = match pat {
Pat::Object(pat) => pat,
Pat::Assign(n) => {
@ -852,6 +853,7 @@ impl RestFolder {
return Pat::Object(ObjectPat {
span,
props,
optional: false,
type_ann,
});
}
@ -885,6 +887,7 @@ impl RestFolder {
props,
span,
type_ann,
optional: false,
})
}
}

View File

@ -1092,9 +1092,7 @@ identical!(
"function foo() {
return () => {
function Bar() {}
Bar.qux = '';
return Bar;
};
}

View File

@ -11,10 +11,10 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
swc_ecma_ast = { version = "0.17.0", path ="../ast" }
swc_ecma_ast = { version = "0.18.0", path ="../ast" }
swc_atoms = { version = "0.2.0", path ="../../atoms" }
swc_common = { version = "0.5.0", path ="../../common" }
swc_ecma_parser = { version = "0.20", path ="../parser", features = ["verify"] }
swc_ecma_parser = { version = "0.21", path ="../parser", features = ["verify"] }
anyhow = "1.0.26"
once_cell = "1"
scoped-tls = "1"

View File

@ -4,13 +4,16 @@ use swc_common::errors::{
};
/// Creates a new handler for testing.
pub(crate) fn new_handler(_: Arc<SourceMapperDyn>) -> (Handler, BufferedError) {
pub(crate) fn new_handler(
_: Arc<SourceMapperDyn>,
treat_err_as_bug: bool,
) -> (Handler, BufferedError) {
let e = BufferedError::default();
let handler = Handler::with_emitter_and_flags(
box e.clone(),
HandlerFlags {
treat_err_as_bug: false,
treat_err_as_bug,
can_emit_warnings: true,
..Default::default()
},

View File

@ -46,7 +46,7 @@ pub fn init() {
fn colored_level<'a>(level: log::Level) -> String {
match level {
log::Level::Trace => Color::Cyan.paint("TRACE").to_string(),
log::Level::Debug => Color::Blue.paint("TRACE").to_string(),
log::Level::Debug => Color::Blue.paint("DEBUG").to_string(),
log::Level::Info => Color::Green.paint("INFO ").to_string(),
log::Level::Warn => Color::Yellow.paint("WARN ").to_string(),
log::Level::Error => Color::Red.paint("ERROR").to_string(),
@ -100,6 +100,7 @@ where
pub struct Tester {
pub cm: Arc<SourceMap>,
pub globals: swc_common::Globals,
treat_err_as_bug: bool,
}
impl Tester {
@ -109,15 +110,22 @@ impl Tester {
Tester {
cm: Arc::new(SourceMap::new(FilePathMapping::empty())),
globals: swc_common::Globals::new(),
treat_err_as_bug: false,
}
}
pub fn no_error(mut self) -> Self {
self.treat_err_as_bug = true;
self
}
/// Run test and print errors.
pub fn print_errors<F, Ret>(&self, op: F) -> Result<Ret, StdErr>
where
F: FnOnce(Arc<SourceMap>, Handler) -> Result<Ret, ()>,
{
let (handler, errors) = self::string_errors::new_handler(self.cm.clone(), false);
let (handler, errors) =
self::string_errors::new_handler(self.cm.clone(), self.treat_err_as_bug);
let result = swc_common::GLOBALS.set(&self.globals, || op(self.cm.clone(), handler));
match result {
@ -131,7 +139,8 @@ impl Tester {
where
F: FnOnce(Arc<SourceMap>, Handler) -> Result<Ret, ()>,
{
let (handler, errors) = self::diag_errors::new_handler(self.cm.clone());
let (handler, errors) =
self::diag_errors::new_handler(self.cm.clone(), self.treat_err_as_bug);
let result = swc_common::GLOBALS.set(&self.globals, || op(self.cm.clone(), handler));
let mut errs: Vec<_> = errors.into();